インターフェイス定義についてMSDNを調べていたところ、次のように表示されました。IEnumerable<T>
public interface IEnumerable<out T> : IEnumerable
なぜ T が と定義されているのか疑問に思っていましたがout
、なぜですか?
public interface IEnumerable<T> : IEnumerable
これの理由は何ですか?
インターフェイス定義についてMSDNを調べていたところ、次のように表示されました。IEnumerable<T>
public interface IEnumerable<out T> : IEnumerable
なぜ T が と定義されているのか疑問に思っていましたがout
、なぜですか?
public interface IEnumerable<T> : IEnumerable
これの理由は何ですか?
詳細については、こちらをご覧ください。
はout
、型パラメーターを共変にします。つまり、型または派生型のいずれかを使用できます。この方法はジェネリックでのみ機能することに注意してくださいout
。メソッド シグネチャで使用する場合は、別の意味になります (おそらく既にご存じでしょうが)。
参照ページからの例を次に示します。
// Covariant interface.
interface ICovariant<out R> { }
// Extending covariant interface.
interface IExtCovariant<out R> : ICovariant<R> { }
// Implementing covariant interface.
class Sample<R> : ICovariant<R> { }
class Program
{
static void Test()
{
ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();
// You can assign istr to iobj because
// the ICovariant interface is covariant.
iobj = istr;
}
}
ご覧のとおり、インターフェイス シグネチャの を使用すると、 がから派生するように、 を変数out
に割り当てることができます。キーワードがないと、型が異なるため、これを行うことはできません。ICovariant<String>
ICovariant<Object>
String
Object
out
共分散 (および関連する反分散) の詳細については、こちらを参照してください。
他の回答が指摘しているようにIEnumerable
、.NET 4 でのみ共変になりました。次のようなコードを記述しようとしています。
IEnumerable<Object> strings = new List<string>();
.NET 4 以降のバージョンではコンパイルされますが、以前のバージョンではコンパイルされません。
out
型パラメーター指定子は、共分散を示します。
実際には、
2 つのインターフェイスを定義するとします。
interface ISomeInterface<T>
{
}
interface ISomeCovariantInterface<out T>
{
}
次に、このように実装します。
class SomeClass<T> : ISomeInterface<T>, ISomeCovariantInterface<T>
{
}
次に、このコードをコンパイルしようとします。
ISomeCovariantInterface<object> covariant = new SomeClass<string>(); // works
ISomeInterface<object> invariant = new SomeClass<string>(); // fails
// Cannot implicitly convert type 'SomeClass<string>' to 'ISomeInterface<object>'.
// An explicit conversion exists (are you missing a cast?)
これは、標準インターフェイスではできないのに対し、共変インターフェイスではより多くの派生インスタンスが許可されるためです。
これを達成するには:
class Base {}
class Derived : Base {}
List<Derived> list = new List<Derived>();
IEnumerable<Base> sequence = list;