这是 C# 4 中的协方差错误吗? [英] Is this a covariance bug in C# 4?
问题描述
在下面的一段代码中,我希望能够从 elements
隐式转换为 baseElements
因为 TBase
可以隐式转换为 IBase
.
In the following piece of code I expected to be able to implicitly cast from elements
to baseElements
because TBase
is implicitly convertible to 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;
}
}
但是,我收到了评论中提到的错误.
However, I get the error that is mentioned in the comment.
引用规范:
A 类型 T
可以方差转换为类型 T
如果 T
> 是使用变体类型参数 T<X1, …, Xn>
声明的接口或委托类型,并且对于每个变体类型参数 Xi
,以下条件之一成立:
A type
T<A1, …, An>
is variance-convertible to a typeT<B1, …, Bn>
ifT
is either an interface or a delegate type declared with the variant type parametersT<X1, …, Xn>
, and for each variant type parameterXi
one of the following holds:
Xi
是协变的,并且存在从Ai
到Bi
Xi
is covariant and an implicit reference or identity conversion exists fromAi
toBi
Xi
是逆变的,并且存在从 Bi
到 Ai
Xi
is contravariant and an implicit reference or identity conversion exists from Bi
to Ai
Xi
是不变的,存在从 Ai
到 Bi
Xi
is invariant and an identity conversion exists from Ai
to Bi
检查我的代码,它似乎与规范一致:
Checking my code, it appears to be consistent with the spec:
IEnumerable
是一种接口类型
IEnumerable
是用变体类型参数声明的
IEnumerable<out T>
is declared with variant type parameters
T
是协变的
存在从 TBase
到 IBase
那么 - 这是 C# 4 编译器中的错误吗?
So - is it a bug in the C# 4 compiler?
推荐答案
Variance 仅适用于引用类型(或存在 identity 转换).不知道TBase
是引用类型,除非你加上:class
:
Variance only works for reference-types (or there is an identity conversion). It is not known that TBase
is reference type, unless you add : class
:
public void Foo<TBase>() where TBase : class, IBase
因为我可以写一个:
public struct Evil : IBase {}
这篇关于这是 C# 4 中的协方差错误吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!