Is this a covariance bug in C# 4?
在下面的代码中,我希望能够隐式地从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public interface IBase { } public interface IDerived : IBase { } public class VarianceBug { public void Foo<TBase>() where TBase : IBase { IEnumerable<TBase> elements = null; IEnumerable<IDerived> derivedElements = null; IEnumerable<IBase> baseElements; // works fine baseElements = derivedElements; // error CS0266: Cannot implicitly convert type // 'System.Collections.Generic.IEnumerable<TBase>' to // 'System.Collections.Generic.IEnumerable<IBase>'. // An explicit conversion exists (are you missing a cast?) baseElements = elements; } } |
但是,我得到了评论中提到的错误。
从规范中引用:
A type
T is variance-convertible to a typeT ifT is either an interface or a delegate type declared with the variant type parametersT , and for each variant type parameterXi one of the following holds:
Xi is covariant and an implicit reference or identity conversion exists fromAi toBi
Xi is contravariant and an implicit reference or identity conversion exists fromBi toAi
Xi is invariant and an identity conversion exists fromAi toBi
检查我的代码,它似乎与规范一致:
IEnumerable 是接口类型IEnumerable 用变量类型参数声明T 是协变的存在从
TBase 到IBase 的隐式引用转换。
那么-这是C 4编译器中的一个bug吗?
差异仅适用于引用类型(或存在标识转换)。不知道
1 | public void Foo<TBase>() where TBase : class, IBase |
因为我可以写:
1 | public struct Evil : IBase {} |
马克是对的-我正要贴同样的回答。
请参见协方差和反方差常见问题解答:
http://blogs.msdn.com/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
从常见问题:
"仅当类型参数是引用类型时才支持差异。"
值类型不支持差异
以下内容也无法编译:
1 2 | // int is a value type, so the code doesn't compile. IEnumerable<Object> objects = new List<int>(); // Compiler error here. |