所以我有一个名为VariableSeries的泛型类,一个名为Indicator的抽象类,派生自它,然后是实现该抽象类的各种类(让我们称之为指示符)。我希望有一个指标列表,并能够使用它。
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];
}
}
...
}
我有一个从VariableSeries派生的Indicator类:
public abstract class Indicator<T> : VariableSeries<T>
{
...
}
现在我想要一个各种类型的指标列表。我的第一个想法就是声明一个List,但这并没有真正起作用。我不能只是抛出一个接口并转换为它,因为我需要使用索引,它使用泛型类型。
所以,假设我有以下指标(许多之一):
public class MovingAverage<T> : Indicator<double>
{
...
}
有没有办法做到以下几点:
List<???> Indicators = new List<???>();
Indicators.Add(new MovingAverage<type is provided dynamically>());
do stuff with Indicators[0][0];
也许某种方式在不必指定类型的情况下转换为泛型类,如((VariableSeries&lt;&gt;)指标[0])[0]?
答案 0 :(得分:1)
???
中的List<???>
必须是具体类型。在您的情况下,这种具体类型必须是共同的基本类型或接口。
所有类共享一个基本类型VariableSeries<T>
,但这个类不具体/具体。所以List<VariableSeries<T>>
是不可能的。
如果您的所有注明人都使用通用类型double
,那么您可以使用List<VariableSeries<double>>
,但我担心情况并非如此。
问题是:你要对这个清单做什么?通过它们迭代然后是什么?问他们的价值?有什么价值?什么类型?一双?一串?编译器无法知道!
一种解决方案可能是创建这样的界面:
public interface IVariableSeries
{
object this[int index] { get; }
}
在VariableSeries<T>
中明确地实现此界面,并在列表中使用此界面作为具体类型:List<IVariableSeries>
。
答案 1 :(得分:0)
您可以使抽象类实现一个接口,该接口包含所有类共有的所有方法,并且没有类型参数。
class VariableSeries<T> : IUntypedInterface
然后你可以使用List<IUntypedInterface>
来获取所有这些。
答案 2 :(得分:0)
你可以使用反射做一些事情。例如,您可以使用以下内容创建具有动态T的MovingAverage:
Type dynamicType = typeof(int); // or any other, e.g. user selected type
var instance = (dynamic)Activator.CreateInstance(typeof(MovingAverage<>).CreateGenericType(dynamicType));
问题当然是你在编译时不知道实例的类型。因此,你不能调用它上面的任何方法,你不能转换它当然在编译时不知道类型。这就是我把它包装成动态的原因。您可以调用任何方法,它将在后台反映到该类型并查找您调用的方法签名。
您可以通过执行
检查实例是否为MovingAverage<>
typeof(MovingAverage<>).Equals(instance.GetType().GetGenericTypeDefinition())
请注意,当实例实际上是MovingAverage的派生类型时,这将返回false。你也可以检查一下,但它有点复杂。
走动态路线当然是一种语言中的危险路径,否则会非常依赖于静态类型检查。您将无法获得重构支持,您将不得不测试很多代码。一个拼写错误,您的程序将抛出异常。
另外,我建议你熟悉.Net反思。你正在进入一个危险的世界。
答案 3 :(得分:0)
添加泛型方法并将类型传递给该方法。这段代码将采用通用方法。
列表指标=新列表(); Indicators.Add(new MovingAverage());