Reputation: 13
I am relatively new to C# and I would like to create a list of generic objects.
Here is how I try to do it:
I create a base class:
public class BaseClass
{
}
And I inherit a generic class from the base class:
public class GenericClass<T> : BaseClass where T: struct
{
public T data;
public GenericClass(T value)
{
data = value;
}
public T doSomething()
{
return (T)(data * (dynamic)0.826f);
}
}
Then I can create a list of base class:
List<BaseClass> ListOfGenericClasses = new List<BaseClass>();
And I can add instances of the inherited geneic class:
ListOfGenericClasses.Add(new GenericClass<int>(100));
ListOfGenericClasses.Add(new GenericClass<byte>(101));
ListOfGenericClasses.Add(new GenericClass<float>(10.1f));
ListOfGenericClasses.Add(new GenericClass<double>(100.10));
ListOfGenericClasses.Add(new GenericClass<ulong>(9999999999));
ListOfGenericClasses.Add(new GenericClass<long>(-9999999999));
ListOfGenericClasses.Add(new GenericClass<uint>(62389));
ListOfGenericClasses.Add(new GenericClass<sbyte>(-103));
I also can invoke each objects method:
string s = "";
s += ((GenericClass<int>)(ListOfGenericClasses[0])).doSomething() + " # ";
s += ((GenericClass<byte>)(ListOfGenericClasses[1])).doSomething() + " # ";
s += ((GenericClass<float>)(ListOfGenericClasses[2])).doSomething() + " # ";
s += ((GenericClass<double>)(ListOfGenericClasses[3])).doSomething() + " # ";
s += ((GenericClass<ulong>)(ListOfGenericClasses[4])).doSomething() + " # ";
s += ((GenericClass<long>)(ListOfGenericClasses[5])).doSomething() + " # ";
s += ((GenericClass<uint>)(ListOfGenericClasses[6])).doSomething() + " # ";
s += ((GenericClass<sbyte>)(ListOfGenericClasses[7])).doSomething();
MessageBox.Show(s);
And here comes the question: how do I get the value of each instance in the list generally?
I try to do something like this:
string s = "";
for (int i = 0; i < ListOfGenericClasses.Count; i++)
{
s += ((GenericClass<ListOfGenericClasses[i].GetType().GetGenericArguments()[0]>)(ListOfGenericClasses[i])).dosdoSomething() + " # ";
}
MessageBox.Show(s);
I have the following error message: "Using the generic type 'GenericClass requires 1 type argument'"
EDIT: sorry guys I could have been more precize when asking my question: my point was not to use the return value to build a string it was just for seeing the result on screen
Any help is much apreciated,
Thanks in advance
Upvotes: 1
Views: 2615
Reputation: 32740
I'd approach it in a slightly different way:
public class BaseClass
{
public virtual string DoSomethingToString() { throw new NotImplementedException(); }
}
Then you'd implement your derived class as follows:
public class GenericClass<T> : BaseClass where T: struct
{
public T data;
public GenericClass(T value)
{
data = value;
}
public T DoSomething()
{
return (T)(data * (dynamic)0.826f);
}
public override string DoSomethingToString()
{
return DoSomething().ToString();
}
}
Now you can iterate List<BaseClass>
and directly call each element's DoSomethingToString()
method.
Upvotes: 4
Reputation: 791
Does this do what you want?
string s = "";
for (int i = 0; i < ListOfGenericClasses.Count; i++)
{
Type type = ListOfGenericClasses[i].GetType();
dynamic d = Convert.ChangeType(ListOfGenericClasses[i], type);
s += d.doSomething() + " # ";
}
It looks like you are trying to implement a union type. I am sure there must be better ways than this.
Upvotes: 1
Reputation: 81
First use stringBuilder to concat strings, you can cast your object to dynamic to invoke the method you need dynamically:
var stringbuilder = new StringBuilder();
foreach (var l in ListOfGenericClasses)
{
var st = (l as dynamic).doSomething() + " # ";
stringbuilder.Append(st);
}
MessageBox.Show(stringbuilder.ToString());
Upvotes: 0
Reputation: 12815
You would need to use reflection to get the type
and then from that get the method which you can then invoke:
string s = "";
for (int i = 0; i < ListOfGenericClasses.Count; i++)
{
s += ListOfGenericClasses[i].GetType()
.GetMethod("doSomething")
.Invoke(ListOfGenericClasses[i], null);
}
However, I would recommend you take the approach as suggested by @corak in the comments and by @InBetween in their answer and create a virtual method in BaseClass
and override it in GenericClass
.
Upvotes: 0
Reputation: 1775
Should you use Generics? I re-wrote your app and solved the problem by removing Generics
public class GenericClass : BaseClass
{
public object data;
public GenericClass(object value)
{
this.data = value;
}
public object doSomething()
{
return (object)(this.data * (dynamic)0.826f);
}
}
Then I did it:
for (var i = 0; i < ListOfGenericClasses.Count; i++)
{
s += ListOfGenericClasses[i].doSomething() + " # ";
}
Upvotes: 0