I have two classes and I've been able to instantiate one class in the other, but when ever I try to use the instantiated class, I get an error. I can't use the instantiated class and VS even reports that instantiated class doesn't exist. Please why is that?
public class GradeBook
{
public GradeBook()
{
gradesList = new List<float>();
}
public void AddGrades(float grades)
{
gradesList.Add(grades);
}
List<float> gradesList;
public List<float> GradesList
{
get
{
return gradesList;
}
set
{
gradesList = value;
}
}
}
public class GradeStatistics
{
GradeBook aveg = new GradeBook();
//This is where the error occurs
aveg.GradesList;
}
A class cannot contain code, unless it is in a method, property, etc. Your code which creates the instance and accesses its property, is not. Create a new method in your class which contains your code. Furthermore: you should do something with the value from the property:
public class GradeStatistics
{
public void MyMethod()
{
GradeBook aveg = new GradeBook();
var result = aveg.GradesList;
}
}
First
You could use just the property for the List object and your method to
add items will be obsolete since List has an own method to add items.
public class GradeBook
{
// Property of type List (short version)
public List<float> GradesList {get; set;}
public GradeBook()
{
GradesList = new List<float>();
}
}
as already mentioned in the comments you need to use the GradeBook object inside the constructor or a method like
public class GradeStatistics
{
// constructor
public GradeStatistics()
{
GradeBook aveg = new GradeBook();
//This will stop the error to occur
//
aveg.GradesList.Add(0.65f);
}
}
or you create also a property in the new class
public class GradeStatistics
{
public GradeBook aveg {get; set;}
// constructor
public GradeStatistics()
{
// from now on you can use it also in methods
aveg = new GradeBook();
}
public void clearForeignList()
{
this.aveg.GradesList.Clear();
}
}
Check you code once again and look #martin-mulder answer. Here's a perfectly wokring code:
public class GradeBook
{
public GradeBook()
{
gradesList = new List<float>();
}
public void AddGrades(float grades)
{
gradesList.Add(grades);
}
List<float> gradesList;
public List<float> GradesList
{
get
{
return gradesList;
}
set
{
gradesList = value;
}
}
}
public class GradeStatistics
{
public void MyMethod()
{
GradeBook aveg = new GradeBook();
var x = aveg.GradesList;
}
}
Related
I have a ParentClass. Two classes are inherit from it, FirstChildClass and SecondChildClass. A class MultipleValueTypes contains a Dictionary and a method that adds values to it. My intention is to be able to pass values of different classes, which inherit from the same abstract class to the value parameter of the Dictionary. Therefore, I initialize the dictionary with the value List<ParentClass> so that I would be able to add objects made with the child classes to the Dictionary. I can do this, but I cannot access them, therefore in the abstract class I create a way to tell them apart, a virtual method that both the children classes override to return their own class type.
I test the values they return against the enum itself and based on whether the condition is fulfilled, the object would be casted as what it is instead of a List<ParentClass>. Is this the wrong approach? Is this impossible?
I think it should work, because in my thinking the FirstObject and SecondObject are still objects of their respective classes, so casting should work and I should be able to access the overridden method.
What doesn't work: I cannot access the method that returns what type of class it is, because it only gets methods from the List<ParentClass>.
What I've tried so far: searching for a way to access the method, but I did not find any.
What I still need help with: everything mentioned above.
public abstract class ParentClass
{
public string Name { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
}
public class FirstChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public FirstChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the FirstChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
private string _randomvalue;
public string RandomValue { get => _randomvalue; set => _randomvalue = value; }
public SecondChildClass(string Name) : base(Name)
{
}
public void ReturnMessage()
{
Console.WriteLine("This is the SecondChildClass");
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public Dictionary<string, List<ParentClass>> ADictionary = new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if (!ADictionary.ContainsKey(Name))
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
class Program
{
static void Main(string[] args)
{
FirstChildClass FirstObject = new FirstChildClass("FirstObject");
SecondChildClass SecondObject = new SecondChildClass("SecondObject");
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if(TestDictionary.ADictionary["FirstObject"].TypeOfClass() == ParentClass.ChildClasses.FirstChildClass) ///List<ParentClass>' does not contain a definition for 'TypeOfClass' and no accessible extension method 'TypeOfClass' accepting a first argument of type 'List<ParentClass>' could be found (are you missing a using directive or an assembly reference?)
{
TestDictionary.ADictionary["FirstObject"] = (FirstChildClass)TestDictionary.ADictionary["FirstObject"]; ///Cannot convert type 'System.Collections.Generic.List<Dictionary.ParentClass>' to 'Dictionary.FirstChildClass
}
}
}
You forgot to use indexer of the list value of the key of the dictionary here:
==> TestDictionary.ADictionary["FirstObject"][0]
Here is your code now refactored too:
class Program
{
static void Main(string[] args)
{
var FirstObject = new FirstChildClass("FirstObject");
var SecondObject = new SecondChildClass("SecondObject");
FirstObject.ReturnMessage();
SecondObject.ReturnMessage();
MultipleValueTypes TestDictionary = new MultipleValueTypes();
TestDictionary.AddObject("FirstObject", FirstObject);
TestDictionary.AddObject("SecondObject", SecondObject);
if ( TestDictionary.ADictionary["FirstObject"][0].TypeOfClass()
== ParentClass.ChildClasses.FirstChildClass )
{
TestDictionary.ADictionary["FirstObject"][0]
= (FirstChildClass)TestDictionary.ADictionary["FirstObject"][0];
}
Console.ReadKey();
}
}
public abstract class ParentClass
{
public string Name { get; set; }
public string RandomValue { get; set; }
public ParentClass(string Name)
{
this.Name = Name;
}
public virtual void ReturnMessage()
{
Console.WriteLine($"This is the {this.GetType().Name} instance");
}
public virtual ChildClasses TypeOfClass()
{
return ChildClasses.NoChildClass;
}
public enum ChildClasses
{
NoChildClass = 0,
FirstChildClass = 1,
SecondChildClass = 2
}
}
public class FirstChildClass : ParentClass
{
public FirstChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.FirstChildClass;
}
}
public class SecondChildClass : ParentClass
{
public SecondChildClass(string Name)
: base(Name)
{
}
public override ChildClasses TypeOfClass()
{
return ChildClasses.SecondChildClass;
}
}
class MultipleValueTypes
{
public readonly Dictionary<string, List<ParentClass>> ADictionary
= new Dictionary<string, List<ParentClass>>();
public void AddObject(string Name, ParentClass variable)
{
if ( !ADictionary.ContainsKey(Name) )
{
ADictionary.Add(Name, new List<ParentClass>());
}
ADictionary[Name].Add(variable);
}
}
If the intention is to cast the whole list from List<ParentClass> to List<FirstChildClass> and List<SecondChildClass>, then Linq is your friend, just use the Cast function:
List<FirstChildClass> firstChildClasses = TestDictionary.ADictionary["FirstObject"]
.Cast<FirstChildClass>().ToList();
List<SecondChildClass> secondChildClasses = TestDictionary.ADictionary["SecondObject"]
.Cast<SecondChildClass>().ToList();
Main class:
public class Main
{
private string param;
public Main(string param) { this.param = param; }
public List<Foo> Foos
{
get {return GetFoos();}
// add functionality of saving Foo (single item, not the whole list) here?
}
private List<Foo> GetFoos()
{
List<Foo> x = new List<Foo>();
return x;
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
// or maybe here?
}
}
Test class:
public class Test
{
public Test()
{
var main = new Main("hi!");
// usage 1
main.Foos.Find(p => p.Id == 1).Save(); // method visible here
var foo = new Main.Foo();
// usage 2
foo.Save(); // method not visible here
}
}
Comments in the code basically say everything:
1. I want to implement the Save() method of the object Foo.
2. Method can be called only if the Foo object is picked up from the list (usage 1).
3. Method can not be called from the Foo object created alone (usage 2).
4. Method must use private value of the property param passed during initialization of the main class.
You can use an interface to hide the method Save.
To do this, the Save method must be implemented explicitly.
Additionally you need a link to the main object. In your subclass Foo you can access the private attribute from Main directly.
Interface:
public interface IFoo
{
int Id { get; set; }
string Name { get; set; }
void Save();
}
Class:
public class Main
{
private string param;
private List<IFoo> foos = new List<IFoo>();
public Main(string param) { this.param = param; }
public List<IFoo> Foos
{
get { return this.foos; }
}
public void AddFoo(int pnId, string pnName)
{
this.foos.Add(new Foo(this) { Id = pnId, Name = pnName });
}
public class Foo : IFoo
{
private Main moParent;
public Foo() { }
public Foo(Main poParent)
{
this.moParent = poParent;
}
public int Id { get; set; }
public string Name { get; set; }
//Implement interface explicitly
void IFoo.Save()
{
if (this.moParent == null)
throw new InvalidOperationException("Parent not set");
Console.WriteLine($"Save with Param: {this.moParent.param}, Id: {this.Id} Name: {this.Name}");
//Save Item
}
}
}
Usage:
var main = new Main("hi!");
main.AddFoo(1, "Foo1");
// usage 1
main.Foos.Find(p => p.Id == 1).Save(); // method visible here
var foo = new Main.Foo();
// usage 2
//foo.Save(); // Save is not visible here
I have class Important and some objects of this class created. I want allow user to choose main object of this class. Have a look at code below:
public class Program
{
public static void Main(string[] args)
{
Important imp1 = new Important("Important 1");
Important imp2 = new Important("Important 2");
Important imp3 = new Important("Important 3");
imp2.SetMostImportant();
Console.Write(Important.MostImportant.Name);
}
public class Important
{
public Important(string name)
{
Name = name;
if(MostImportant == null)
SetMostImportant();
}
public string Name { get; private set; }
public static Important MostImportant { get; private set; }
public void SetMostImportant()
{
MostImportant = this;
}
}
}
Is it good solution? If not, please tell me why not.
Before, to achieve this kind of things I just created boolean field named e.g. IsMainObject and, when I wanted to change main object, I iterated through all objects (or group of object) of specific class except element that I want to be main, and changed boolean to false, in my new candidate I simply set flag to true. Example below:
public class Program
{
public static void Main(string[] args)
{
Important imp1 = new Important("Important 1");
Important imp2 = new Important("Important 2");
Important imp3 = new Important("Important 3");
List<Important> list = new List<Important> { imp1, imp2, imp3 };
foreach(var item in list.Where(x => x.Name != "Important 2"))
{
item.SetMostImportant(false);
}
imp2.SetMostImportant(true);
Console.Write(list.FirstOrDefault(x => x.MostImportant == true).Name);
}
public class Important
{
public Important(string name)
{
Name = name;
}
public string Name { get; private set; }
public bool MostImportant { get; private set; }
public void SetMostImportant(bool val)
{
MostImportant = val;
}
}
}
I don't like this solution because:
I don't know if MostImportant is true for more than one objects without iterating.
I need to write extra-code to handle much more cases.
I don't have possibility to always iterate through all instances of specific class (groups not always are enough).
... and much more, but you got the idea.
public static Important MostImportant { get; private set; }
is a fine solution, and much better than
public bool MostImportant { get; private set; }
It's not uncommon to have a static property of the type that it's inside of when implementing "singleton" classes. I've written code that resembles this:
class MyClass
{
public static MyClass Instance { get; private set; }
public MyClass()
{
if (Instance == null)
{
Instance = this;
}
else
{
throw new Exception("MyClass already instantiated.");
}
}
}
I've been experimenting with detecting changes in plain objects in C#. The aim being to have a container-type class for a bunch of data objects that can react when any one of them changes. For fun I wanted to see if all the work could be done in the container class, rather than resort to properties and dirty flags or events on the objects themselves.
What I'm curious about is whether there is a smart, fast and efficient way of doing this. My attempt is below, and it's none of those (the 'CheckStates' method would need to be called every frame for a start!) I've restricted it to only allow one instance per type, which suits my needs.
Note that an object passed in might be as follows:
[Serializable]
public class PlayerInfo
{
public string name = string.Empty;
public int score = 0;
}
Then the container:
public class AppState
{
private class StateData
{
public System.Object instance = null;
public Byte[] currentState = new Byte[0];
public Byte[] previousState = new Byte[0];
}
private Dictionary<Type, StateData> _allStates = new Dictionary<Type, StateData>();
private BinaryFormatter _formatter = new BinaryFormatter();
private MemoryStream _memoryStream = new MemoryStream();
public T GetState<T>() where T : class, new()
{
T state = default(T);
var stateType = typeof(T);
StateData stateData;
if(_allStates.TryGetValue(stateType, out stateData))
{
state = ReadData<T>(stateData);
}
else
{
var newState = CreateData<T>(out state);
_allStates[stateType] = newState;
}
return state;
}
public void CheckStates()
{
foreach(var state in _allStates)
{
if(HasChanged(state.Value))
{
Console.WriteLine(state.Key.ToString() + " has changed");
UpdateState(state.Value);
}
}
}
private StateData CreateData<T>(out T instance) where T : class, new()
{
instance = new T();
var stateData = new StateData();
stateData.instance = instance;
_formatter.Serialize(_memoryStream, instance);
var bytes = _memoryStream.ToArray();
stateData.currentState = bytes;
stateData.previousState = bytes;
return stateData;
}
private T ReadData<T>(StateData data) where T : class, new()
{
return data.currentState as T;
}
private bool HasChanged(StateData data)
{
_memoryStream.Position = 0;
_formatter.Serialize(_memoryStream, data.instance);
var current = _memoryStream.ToArray();
var previous = data.previousState;
if(current.Length != previous.Length)
{
return true;
}
for(int i = 0; i < current.Length; ++i)
{
if(current[i] != previous[i])
{
return true;
}
}
return false;
}
private void UpdateState(StateData data)
{
_memoryStream.Position = 0;
_formatter.Serialize(_memoryStream, data.instance);
data.previousState = _memoryStream.ToArray();
}
}
Alternatives I could think of were:
use structs instead of serializable classes (being forced to pass by value would mean that any change would have to go through a 'set' method on the container)
have the AppState's 'GetState' method return an IDisposable wrapper, which on Dispose could trigger a check for changes on that type (only problem is that there's nothing to stop someone from storing a reference to the object and modifying it without the container knowing)
EDIT: should add that it doesn't need to be thread-safe
I don't regard serializable classes as POCO, because you're engineering the classes so that they work with your change detection mechanism. So I wouldn't call them plain.
Your alternatives:
use structs instead of serializable classes
Don't use mutable structs Why are mutable structs “evil”?. And if your struct is immutable, then you might as well pass by reference, i.e. have a class.
have the 'get' method return an IDisposable wrapper
I'm not sure what get method you are referring to.
Proxy
One alternative is to allow a descendant proxy to react to calls to the setters:
public class PlayerInfo
{
public virtual string Name { get; set; }
public virtual int Score { get; set; }
}
public class PlayerInfoDetection : PlayerInfo
{
public int Revision { get; private set; }
public override string Name
{
set
{
base.Name = value;
Revision++;
}
}
public override int Score
{
set
{
base.Score = value;
Revision++;
}
}
}
private static void Example()
{
PlayerInfo pi = new PlayerInfoDetection();
Console.WriteLine(((PlayerInfoDetection)pi).Revision);
pi.Name = "weston";
Console.WriteLine(((PlayerInfoDetection)pi).Revision);
pi.Score = 123;
Console.WriteLine(((PlayerInfoDetection)pi).Revision);
}
This is how NHibernate "watches" objects fetched from the database, and why every object property must be virtual in NHibernate.
Aspect orientated
The same could be achieved with a product like post sharp where you could annotate your class to tell it when the revision must be changed.
public class PlayerInfo
{
public int Revision { get; private set; }
public string Name { get; [IncreaseRevision] set; }
public int Score { get; [IncreaseRevision] set; }
}
Making use of a well implemented hash function
Hash functions should not change their value while the object is in a container such as a hash set. We can make use of this to detect changes.
Drawback Note that any Hash collisions will yield incorrect results. This includes duplicates.
[TestClass]
public class ChangeDetectUnitTest
{
public class ChangeDetectList<T>
{
private readonly List<T> list = new List<T>();
private readonly ISet<T> hashes = new HashSet<T>();
public bool HasChanged(T t)
{
return !hashes.Contains(t);
}
public void Add(T t)
{
list.Add(t);
hashes.Add(t);
}
public void Reset()
{
hashes.Clear();
foreach (var t in list)
hashes.Add(t);
}
}
public class PlayerInfo
{
public string Name { get; set; }
public int Score { get; set; }
public override int GetHashCode()
{
//every field that you want to detect must feature in the hashcode
return (Name ?? "").GetHashCode() * 31 + Score;
}
public override bool Equals(object obj)
{
return Equals(obj as PlayerInfo);
}
public bool Equals(PlayerInfo other)
{
if (other == null) return false;
return Equals(other.Name, Name) && Score == Score;
}
}
private ChangeDetectList<PlayerInfo> list;
[TestInitialize]
public void Setup()
{
list = new ChangeDetectList<PlayerInfo>();
}
[TestMethod]
public void Can_add()
{
var p1 = new PlayerInfo();
list.Add(p1);
Assert.IsFalse(list.HasChanged(p1));
}
[TestMethod]
public void Can_detect_change()
{
var p1 = new PlayerInfo();
list.Add(p1);
p1.Name = "weston";
Assert.IsTrue(list.HasChanged(p1));
}
[TestMethod]
public void Can_reset_change()
{
var p1 = new PlayerInfo();
list.Add(p1);
p1.Name = "weston";
list.Reset();
Assert.IsFalse(list.HasChanged(p1));
}
}
Original Source Code
I've got a simple business object in my BusinessObjects.dll file:
namespace BusinessObjects
{
public class MyClass
{
public MyClass()
{
DateTime = DateTime.Now;
}
public DateTime DateTime { get; set; }
}
}
In my SharedUI.dll I've got this "Context-provider" class, that I use to hold a referece to the currently selected MyClass - remember this is a simplyfied example :)...
namespace SharedUI
{
public class AppContext
{
[Export]
public MyClass SelectedMyClass { get; private set; }
public void SetupContext(MyClass myClass)
{
SelectedMyClass = myClass;
}
public static AppContext Context
{
get
{
if (context == null)
{
context = new AppContext();
}
return context;
}
}
private static AppContext context;
}
}
My MefTest.exe has this class:
namespace MefTest
{
public class Program
{
[Import]
public MyClass MyClass { get; set; }
private void Compose()
{
var ventSystem = new MyClass();
AppContext.Context.SetupContext(ventSystem);
var executingAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var contextAssembly = new AssemblyCatalog(Assembly.LoadFile(string.Format(#"{0}\SharedUI.dll", Environment.CurrentDirectory)));
var catalog = new AggregateCatalog(executingAssembly, contextAssembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
private void Run()
{
Compose();
// MyClass is always null in the next line?
Console.WriteLine(MyClass.DateTime.ToString());
Console.ReadKey();
}
private static void Main(string[] args)
{
var p = new Program();
p.Run();
}
}
}
I'm a MEF rookie so please bear with me :)
UPDATED Source Code with suggestions from Daniel Plaisted
MyClass source is the same...
SharedUI.dll now looks like this:
namespace SharedUI
{
[Export]
public class AppContext
{
[Export(typeof(MyClass))]
public MyClass SelectedMyClass { get; private set; }
public void SetupContext(MyClass myClass)
{
SelectedMyClass = myClass;
}
}
}
MefTest.exe now looks like this:
namespace MefTest
{
public class Program
{
[Import]
public MyClass MyClass { get; set; }
[Import]
public AppContext AppContext { get; set; }
private void Compose()
{
var executingAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var contextAssembly = new AssemblyCatalog(Assembly.LoadFile(string.Format(#"{0}\SharedUI.dll", Environment.CurrentDirectory)));
var catalog = new AggregateCatalog(executingAssembly, contextAssembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
var myClass = new MyClass();
AppContext.SetupContext(myClass);
}
private void Run()
{
Compose();
// AppContext.SelectedMyClass is NOT null in the next line... which is good I guess :)
Console.WriteLine(AppContext.SelectedMyClass.DateTime.ToString());
// MyClass is always null in the next line?
Console.WriteLine(MyClass.DateTime.ToString());
Console.ReadKey();
}
private static void Main(string[] args)
{
var p = new Program();
p.Run();
}
}
}
What am I doing wrong since I can't get it working?
When MEF needs to get an Export which is on a property of a class, it will create an instance of the class and call the property getter. So MEF is creating a new instance of your AppContext, different than the static AppContext.Context instance. The instance MEF creates doesn't have the SelectedMyClass property set on it, which is why your import ends up being null.
The problem is:
[Import] public MyClass MyClass { get; set; }
There are no [Export]s defined for MyClass. MEF will compose this appplication based on stuff it "knows", and since it does not know "MyClass"...
I noticed this one:
[Export] public MyClass SelectedMyClass { get; private set; }
This means you are trying to trick MEF into updating one of its parts from time to time? The solution to this would be to create a custom Catalog which contains "runtime" objects, in which you can updated the exported value for MyClass whenever you want. The current implementation will never resolve MyClass...
[edited:]
You can decorate a member as well, but you'll have to add the class type there. So this will work:
[Export(typeof(MyClass)] public MyClass SelectedMyClass { get; private set; }
You put your Export attribute in the wrong place.
You should put it on the definition of MyClass like so:
namespace BusinessObjects
{
[Export]
public class MyClass
{
public MyClass()
{
DateTime = DateTime.Now;
}
public DateTime DateTime { get; set; }
}
}
And then use the [Import] attribute wherever you want an instance of this class.
Remark: You cannot use MEF to move a specific instance of a class (not like this).
MEF is used to create instances of a requested type and inject them at indicated places.
To learn more about MEF check out the project's page at CodePlex.