次のコードでは、がに暗黙的に変換可能であるため、から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
は共変であり、からへの暗黙の参照またはID変換が存在Ai
しますBi
Xi
は反変であり、からへの暗黙の参照またはID変換が存在Bi
しますAi
Xi
は不変であり、ID変換はからに存在Ai
しますBi
私のコードを確認すると、仕様と一致しているようです。
IEnumerable<out T>
インターフェイスタイプですIEnumerable<out T>
バリアント型パラメーターで宣言されますT
共変ですTBase
からへの暗黙の参照変換が存在しますIBase
それで-それはC#4コンパイラのバグですか?