问题
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.
Quoting from the spec:
A type
T<A1, …, An>is variance-convertible to a typeT<B1, …, Bn>ifTis either an interface or a delegate type declared with the variant type parametersT<X1, …, Xn>, and for each variant type parameterXione of the following holds:
Xiis covariant and an implicit reference or identity conversion exists fromAitoBi
Xiis contravariant and an implicit reference or identity conversion exists fromBitoAi
Xiis invariant and an identity conversion exists fromAitoBi
Checking my code, it appears to be consistent with the spec:
IEnumerable<out T>is an interface typeIEnumerable<out T>is declared with variant type parametersTis covariantan implicit reference conversion exists from
TBasetoIBase
So - is it a bug in the C# 4 compiler?
回答1:
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
since I could write a:
public struct Evil : IBase {}
回答2:
Marc is correct - I was just about to paste the same response.
See the Covariance & Contravariance FAQ:
http://blogs.msdn.com/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
From the FAQ:
"Variance is supported only if a type parameter is a reference type."
Variance is not supported for value types
The following doesn’t compile either:
// 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/is-this-a-covariance-bug-in-c-sharp-4