在下面的代码中,我希望能够隐式地从elements转换到baseElements,因为TBase可以隐式转换为IBase。
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;
}
}但是,我得到了注释中提到的错误。
引用规范的话:
类型
T<A1, …, An>是可转换为类型T<B1, …, Bn>的类型,如果T是一个接口或一个委托类型,并声明了变量类型参数T<X1, …, Xn>,并且对于每个变量类型参数Xi,有以下一种情况:
Xi是协变的,从Ai到Bi存在隐式引用或身份转换。
Xi是反变体,从Bi到Ai存在隐式引用或身份转换。
Xi是不变的,从Ai到Bi存在身份转换。
检查我的代码,它似乎与规范一致:
IEnumerable<out T>是一种接口类型IEnumerable<out T>是用可变类型参数声明的。
T是协变从IBase到
那么--这是C# 4编译器中的一个bug吗?
发布于 2010-05-06 18:16:23
方差只适用于引用类型(或存在身份转换)。除非添加TBase,否则不知道: class是引用类型。
public void Foo<TBase>() where TBase : class, IBase因为我可以写一个:
public struct Evil : IBase {}发布于 2010-05-06 18:20:26
马克是对的-我正要贴同样的回复。
参见协方差和反方差常见问题:
http://blogs.msdn.com/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
从常见问题:
“只有当类型参数是引用类型时,才支持方差。”
值类型不支持方差
以下内容也没有编译:
// int is a value type, so the code doesn't compile.
IEnumerable<Object> objects = new List<int>(); // Compiler error here.https://stackoverflow.com/questions/2783233
复制相似问题