まず、C#ではクラスは常に不変です。次のようなクラスを宣言することはできません。
// Invalid
public class Foo<out T>
第二に、そしてあなたが与えた例にとってより重要なことは、 type の値を受け入れて返すメンバーがList<T>
あるため、共変または反変であると宣言することはできませんでした。T
T
それが共変であると想像してください。次に、これを書くことができます(明らかなFruit
クラス階層のために):
List<Banana> bunchOfBananas = new List<Banana>();
// This would be valid if List<T> were covariant in T
List<Fruit> fruitBowl = bunchOfBananas;
fruitBowl.Add(new Apple());
Banana banana = bunchOfBananas[0];
最後の行は何をすると思いますか? Apple
基本的に、実際の実行時の型が であるオブジェクトへの参照を追加することはできませんList<Banana>
。バナナの束にリンゴを加えると、りんごが落ちます。私を信じてください、私は試しました。
最後の行は型に関して安全でなければなりません - 内の唯一の値は、またはサブクラスのインスタンスへの参照であるList<Banana>
必要があります。null
Banana
クラスが論理的に共変である可能性がある場合でも、クラスが共変になれない理由については...実装レベルで問題が発生し、プログラミングレベルでも非常に制限されると思います。たとえば、次のように考えてください。
public class Foo<out T> // Imagine if this were valid
{
private T value;
public T Value { get { return value; } }
public Foo(T value)
{
this.value = value;
}
}
それはおそらくまだ無効である必要があります-変数はまだ書き込み可能です。つまり、「in」スロットとしてカウントされます。タイプのすべての変数をT
読み取り専用にする必要があります...そしてそれは初心者向けです。もっと深い問題があるのではないかと強く思います。
純粋なプラグマティズムの観点から言えば、CLR は v2 からのデリゲートとインターフェイスの相違をサポートしています。C# 4 では、この機能を公開するための構文が導入されました。CLR がジェネリック クラスの差異をサポートしたことがあるとは思えません。