Reputation: 115
So I've got a generic class called VariableSeries, an abstract class called Indicator derived from it, and then various classes (let's call them indicators) that implement that abstract class. I want to have a List of indicators and be able to use it.
public class VariableSeries<T>
{
protected List<T> Series;
public int CurrentBar { get; private set; }
public T this[int index]
{
get
{
if (index > CurrentBar)
throw new Exception("Tried to look too far in the past, data does not exist.");
return Series[CurrentBar - index];
}
}
...
}
And I've got an Indicator class that's derived from VariableSeries:
public abstract class Indicator<T> : VariableSeries<T>
{
...
}
Now I want to have a List of indicators of various types. My first idea was to just declare a List, but that doesn't really work. And I can't just throw an interface at it and cast to that, because I need to use the indexation, which makes use of the generic type.
So let's say I've got the following indicator (one of many):
public class MovingAverage<T> : Indicator<double>
{
...
}
Is there any way to do the following:
List<???> Indicators = new List<???>();
Indicators.Add(new MovingAverage<type is provided dynamically>());
do stuff with Indicators[0][0];
Perhaps some sort of way of casting to a generic class without having to specify the type, like ((VariableSeries<>)Indicators[0])[0]?
Upvotes: 1
Views: 187
Reputation: 761
Add a generic method and pass the type to that method. this code will go in generic method.
List Indicators = new List(); Indicators.Add(new MovingAverage());
Upvotes: 0
Reputation: 6465
You can do some stuff using reflection. For example you can create a MovingAverage with a dynamic T using the following:
Type dynamicType = typeof(int); // or any other, e.g. user selected type
var instance = (dynamic)Activator.CreateInstance(typeof(MovingAverage<>).CreateGenericType(dynamicType));
The problem of course is that you don't know the type of instance at compile time. Thus you can't call any methods on it and you can't cast it of course the type isn't known at compile time. That's why I wrapped it as dynamic. You can call any method and it will in the background reflect into that type and look for the method signature that you called.
You can check if instance is a MovingAverage<>
by doing
typeof(MovingAverage<>).Equals(instance.GetType().GetGenericTypeDefinition())
Be aware that this will return false when instance is actually of a derived type of MovingAverage. You can also check that, but it's a bit more complicated.
Going the dynamic route is of course a dangerous path in a language that otherwise relies so much on static type checking. You won't have refactoring support and you will have to test a lot running your code. A single typo and your program will throw an exception.
Also, I would suggest you get familiar with .Net reflection. You're entering a dangerous world.
Upvotes: 0
Reputation: 86600
You can make the abstract class implement an interface with all methods that will be common to all classes and has no type parameters.
class VariableSeries<T> : IUntypedInterface
Then you can use a List<IUntypedInterface>
to get then all together.
Upvotes: 0
Reputation: 12944
The ???
in your List<???>
must be a concrete type. This concrete type must, in your case, a commonly shared basetype or interface.
All your classes share a basetype VariableSeries<T>
but this one is not concrete / specific. So List<VariableSeries<T>>
is not possible.
If all your indicaters would use the generic type double
, than you could use List<VariableSeries<double>>
, but I am afraid that is not the case.
The question is: what are your going to do with that list? Iterate through them and then what? Ask for their value? What value? What type? A double? A string? The compiler cannot know!
One solution could be to create an interface like this:
public interface IVariableSeries
{
object this[int index] { get; }
}
Implement this interface EXPLICITLY in your VariableSeries<T>
and use this interface as your concrete type in your list: List<IVariableSeries>
.
Upvotes: 1