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 type T<B1, …, Bn>
if T
is either an interface or a delegate type declared with the variant type parameters T<X1, …, Xn>
, and for each variant type parameter Xi
one of the following holds:
Xi
is covariant and an implicit reference or identity conversion exists from Ai
to Bi
Xi
is contravariant and an implicit reference or identity conversion exists from Bi
to Ai
Xi
is invariant and an identity conversion exists from Ai
to Bi
Checking my code, it appears to be consistent with the spec:
IEnumerable<out T>
is an interface type
IEnumerable<out T>
is declared with variant type parameters
T
is covariant
an implicit reference conversion exists from TBase
to IBase
So - is it a bug in the C# 4 compiler?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…