是否有可能从基于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
失败。我们争论的问题是它是否实际上是不可能的,或者仅仅是一个语法错误,如果我们知道如何就可以修复。
答案 0 :(得分:3)
C# 4.0 will have that feature.
将在符合某些规则的接口和代理上启用它。不支持List<T>
,因为它是一个具体的类。 IList<T>
也不受支持,因为其方法在T
和in
位置使用out
。
答案 1 :(得分:1)
此
List<Derived> der = new List<Derived>();
List<Base> bas = (List<Base>)der;
是不可能的,永远不可能。这里发生了什么:
Base b = new Base();
bas.Add(b);
KABOOM!是怎么回事如果上述内容合法,bas
只会引用der
而der
则无法添加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>();