使用泛型类型参数进行上传

时间:2010-02-09 18:49:28

标签: c# generics casting

是否有可能从基于T的泛型类“upcast”到基于比T更通用的泛型类?

例如,假设我有一个名为Derived的类,它继承自名为Base的类。我能做这样的事吗:

List<Derived> der = new List<Derived>();
List<Base> bas = (List<Base>) der;

或者,使用接口,有可能做到这样的事情:

List<MyClonableType> specific = new List<MyClonableType>();
List<IClonable> general = (List<IClonable>)specific;

如此处所述,这些示例中的每一个都以InvalidCastException失败。我们争论的问题是它是否实际上是不可能的,或者仅仅是一个语法错误,如果我们知道如何就可以修复。

3 个答案:

答案 0 :(得分:3)

C# 4.0 will have that feature.

将在符合某些规则的接口和代理上启用它。不支持List<T>,因为它是一个具体的类。 IList<T>也不受支持,因为其方法在Tin位置使用out

答案 1 :(得分:1)

List<Derived> der = new List<Derived>(); 
List<Base> bas = (List<Base>)der;

是不可能的,永远不可能。这里发生了什么:

Base b = new Base();
bas.Add(b);

KABOOM!是怎么回事如果上述内容合法,bas只会引用derder则无法添加Base Add尝试执行的实例。 (具体而言,将Base视为Animal,将Derived视为Cat;您无法将List<Cat>投放到List<Animal>,因为那样的话可以将Dog的实例添加到已经失败的列表中,因为它实际上是List<Cat>。)

出于类似的原因

List<MyClonableType> specific = new List<MyClonableType>();  
List<IClonable> general = (List<IClonable>)specific;  

永远不可能。

C# 4.0中,covariance and contravariance的概念将解决其中一些问题。例如,在C#4.0中,这将是合法的:

List<Derived> der = new List<Derived>();
IEnumerable<Base> bas = der;

这是因为IEnumerable<Base>仅吐出Base的实例,并且由于所有Derived都是Base s,这是可以的。换句话说,IEnumerable<Base>说“我知道如何向你抛出Base的实例”,List<Derived>说“我知道如何向你抛出Derived的实例”。但由于所有Derived都是Base s,这意味着List<Derived>也知道如何向您抛出Base的实例。因此,它应该能够分配给IEnumerable<Base>的实例。这是C#4.0中可能的。这是协方差的一个例子。

我必须强调,对于像List<T>这样的类型,它们的方法既吃T又吐出T,这是不可能的。

答案 2 :(得分:0)

有很好的LINQ扩展名:

der.ToList<Base>();