web-dev-qa-db-ja.com

ジェネリックの<out T> vs <T>

<out T><T>の違いは何ですか?例えば:

public interface IExample<out T>
{
    ...
}

vs.

public interface IExample<T>
{
    ...
}
160
Cole Johnson

ジェネリックのoutキーワードは、インターフェイスのタイプTが共変であることを示すために使用されます。詳細については、 共分散と反分散 を参照してください。

古典的な例はIEnumerable<out T>です。 IEnumerable<out T>は共変なので、次のことを行うことができます。

IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;

文字列はオブジェクトから派生するため、論理的には機能するはずですが、これが共変ではない場合、上記の2行目は失敗します。 汎用インターフェイスの違い がC#およびVB.NET(VS 2010を備えた.NET 4)に追加される前は、これはコンパイル時エラーでした。

.NET 4の後、IEnumerable<T>は共変とマークされ、IEnumerable<out T>になりました。 IEnumerable<out T>はその中の要素のみを使用し、それらを追加/変更することはないため、列挙可能な文字列のコレクションをオブジェクトの列挙可能なコレクションとして扱うのは安全です。つまり、covariant

IList<T>にはAddメソッドがあるため、これはIList<T>のような型では機能しません。これが許可されると仮定します:

IList<string> strings = new List<string>();
IList<object> objects = strings;  // NOTE: Fails at compile time

次に電話することができます:

objects.Add(new Image()); // This should work, since IList<object> should let us add **any** object

もちろん、これは失敗します-したがって、IList<T>は共変としてマークできません。

ところで、inのオプションもあります-これは比較インターフェースのようなものによって使用されます。たとえば、IComparer<in T>は逆の動作をします。 IComparer<Foo>インターフェイスはであるため、BarFooのサブクラスである場合、具体的なIComparer<Bar>IComparer<in T>として直接使用できます。反変

192
Reed Copsey

inおよびoutキーワードの使用(共分散と反分散も)を簡単に思い出すために、継承をラッピングとしてイメージできます。

String : Object
Bar : Foo

in/out

52

考えて、

class Fruit {}

class Banana : Fruit {}

interface ICovariantSkinned<out T> {}

interface ISkinned<T> {}

および機能、

void Peel(ISkinned<Fruit> skinned) { }

void Peel(ICovariantSkinned<Fruit> skinned) { }

ICovariantSkinned<Fruit>は共変インターフェイスであり、BananaFruitのタイプであるため、ICovariantSkinned<Fruit>を受け入れる関数はICovariantSkinned<Bananna>またはICovariantSkinned<T>を受け入れることができます。 、

ISkinned<Fruit>を受け入れる関数は、ISkinned<Fruit>のみを受け入れることができます。

44
Jodrell

out T」は、タイプTが「共変」であることを意味します。これにより、Tがジェネリッククラス、インターフェイス、またはメソッドのメソッドで返される(アウトバウンド)値としてのみ表示されるように制限されます。これは、タイプ/インターフェース/メソッドを、Tのスーパータイプを持つ同等のものにキャストできることを意味します。
例えば。 ICovariant<out Dog>ICovariant<Animal>にキャストできます。

30
James World

投稿したリンクから...

ジェネリック型パラメーターの場合、outキーワードは、型パラメーターが共変であることを指定します

編集:もう一度、投稿したリンクから

詳細については、「共分散と反分散(C#およびVisual Basic)」を参照してください。 http://msdn.Microsoft.com/en-us/library/ee207183.aspx

5
Brad Cunningham