重複の可能性:
C# 4.0 のクラスに一般的な差異がないのはなぜですか?
C# (4.0) がジェネリック クラス型で共変性と反変性を許可しないのはなぜですか?
ジェネリック型引数の新しい .NET 4.0 共変性と反変性は、インターフェイスとデリゲートに対してのみ機能します。クラスでもサポートしない理由は何ですか?
重複の可能性:
C# 4.0 のクラスに一般的な差異がないのはなぜですか?
C# (4.0) がジェネリック クラス型で共変性と反変性を許可しないのはなぜですか?
ジェネリック型引数の新しい .NET 4.0 共変性と反変性は、インターフェイスとデリゲートに対してのみ機能します。クラスでもサポートしない理由は何ですか?
型の安全性のために、C# 4.0 はinまたはoutでマークされた型パラメーターに対してのみ共変性/反変性をサポートします。
これがクラスに拡張された場合、出力で型パラメーターをマークする必要があり、これは非常に制限的になります。これが、CLR の設計者が許可しないことを選択した理由である可能性が最も高いです。たとえば、次のクラスを考えてみます。
public class Stack<T>
{
int position;
T[] data = new T[100];
public void Push (T obj) { data[position++] = obj; }
public T Pop() { return data[--position]; }
}
T は入力位置と出力位置の両方で使用されるため、T に out のいずれかとして注釈を付けることは不可能です。したがって、このクラスは共変または反変になることはありません。クラスの共変/反変型パラメーターがサポートされている C# であってもです。
インターフェイスは問題をうまく解決します。次のように 2 つのインターフェイスを定義し、スタックに両方を実装させることができます。
public interface IPoppable<out T> { T Pop(); }
public interface IPushable<in T> { void Push (T obj); }
T は IPoppable では共変であり、IPushable では反変であることに注意してください。これは、IPoppable にキャストするか IPushable にキャストするかによって、T が共変または反変のいずれかになることを意味します。
共変性/反変性がクラスでの使用が制限されるもう 1 つの理由は、型パラメーターをフィールドとして使用することを除外することです。これは、フィールドが効果的に入力操作と出力操作の両方を許可するためです。実際、in または out としてマークされた型パラメーターを使用して、何らかの有用な処理を行うクラスを作成するのは困難です。共変の Enumerable 実装を記述する最も単純なケースでさえ、課題を提示します。まず、どのようにしてソース データをインスタンスに取得しますか?
.NET チームと C# および VB.NET チームのリソースは限られていますが、共分散と反分散に関して彼らが行った作業は、現実世界の問題のほとんどを解決します。型システムは正しく処理するのが非常に複雑です。99.9999% のケースで機能するソリューションは、他のケースで安全でないコードにつながる場合には十分ではありません。
クラス メソッドの共変性と反変性の仕様 (例: "in"/"out") をサポートするためのコスト/時間は、十分に価値があるとは思いません。乗算クラス継承がないため、それらが使用できるケースはほとんどありません。
このサポートを受けるために、.net をさらに 6 か月待ちましたか?
これを考える別の方法は、.net