【发布时间】:2013-08-24 19:07:19
【问题描述】:
参考这个在 Visual Studio 2010 express 中为 C# 编译的测试代码
public class Test
{
class Base { }
class Derived : Base { }
void Test1(IEnumerable<Derived> derived)
{
IEnumerable<Base> b = derived; //This works fine using covariance on IEnumerable
}
void Test2<TDerived, TBase>(TDerived derived) where TDerived : TBase
{
TBase b = derived; //This works fine because TDerived is constrained to derive from TBase
}
void Test3<TDerived, TBase>(IEnumerable<TDerived> derived) where TDerived : TBase
{
IEnumerable<TBase> b = derived; //ERROR: paraphrased: Cannot implicitly convert type IEnumerable<TDerived> to IEnumerable<TBase>
}
}
我试图利用 IEnumerable 的协方差将泛型类型参数的可枚举存储在该类型参数被限制继承的类的可枚举中。这以 Test3 为例。请注意,Test1 和 Test2(分别演示编译时类型的协方差和约束类型的分配)都可以正常编译。这是两种语言功能的组合,对我不起作用。
我可以使用 IEnumerable<TBase> b = derived.Cast<TBase>() 并且 100% 确信如果我的理解没有缺陷,任何演员都不会失败,所以我有一个可用的解决方法。我的问题是,为什么编译器不允许这样做?这是出于某种逻辑原因、编译器疏忽还是我没有想到的其他原因而被禁止?
【问题讨论】:
-
Jon Skeet 已经给出了答案。
IEnumerable<out T>是协变的,但协变仅适用于 C# 中的引用类型。例如,如果der是IEnumerable<int>,则不允许分配IEnumerable<IFormattable> b = der;。所以Test3<int, IFormattable>(der);会是个问题,即使int是IFormattable。
标签: c# generics covariance