Problem
How to create a list of generic types?
Let’s say you have a base class called Parameter. But you can have different parameter types, hence different implementations of operands (+, -, etc). You can have Parameter<int>, Parameter.
How would you create a list of these generics?
One solution would be to create a base class with the same functionality of the generic type and just hide the context parameter.
public class Parameter { public virtual object Value { get; private set; } public Parameter(object value) { this.Value = value; } } public class ParameterGen<T> : Parameter { public new T Value { get; private set; } public ParameterGen(T value) : base(value) { this.Value = mult(value); } }
Now you can do this:
List<Parameter> parameters = new List<Parameter> { new Parameter("a value"), new ParameterGen<int>(2) };
What is wrong with this? It seems that you hided the Value parameter, all works fine. To find out what that this exacly means try the following. Add a modifier of the value in the generic class:
Is this confusing? Well, in fact when you hide a variable, that didn’t just magically disappeared or transformed to the new one, it’s just compiler-ignored. A new variable is created that is not related to the one from the base class.
And of course the expected results are 4 and 2. So by now you duplicated all your values, and of course when with the example of the Action in the constructor it’s obvious that there is place for errors
public class ParameterGen<T> : Parameter { public new T Value { get; private set; } public ParameterGen(T value, Func<T, T> mult) : base(value) { this.Value = mult(value); } }
ParameterGen<int> p = new ParameterGen<int>(2, (x) => x * 2); Console.WriteLine(p.Value); Console.WriteLine(((Parameter)p).Value);
Solution
public abstract class Parameter { public abstract object GetValue(); } public class ParameterGen<T> : Parameter { public T Value { get; set; } public override object GetValue() => Value; public ParameterGen(T value) { this.Value = value; } } class Program { static void Main(string[] args) { List<Parameter> list = new List<Parameter> { new ParameterGen<int>(2), new ParameterGen<string>("da") }; Console.WriteLine(list[0].GetValue()); } }