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 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?
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 {} If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With