16

重複の可能性:
C# 4 で IEnumerable<T> が共変になったのはなぜですか?

インターフェイス定義についてMSDNを調べていたところ、次のように表示されました。IEnumerable<T>

public interface IEnumerable<out T> : IEnumerable

なぜ T が と定義されているのか疑問に思っていましたがout、なぜですか?

public interface IEnumerable<T> : IEnumerable

これの理由は何ですか?

4

4 に答える 4

21

詳細については、こちらをご覧ください

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>StringObjectout

共分散 (および関連する反分散) の詳細については、こちらを参照してください。

他の回答が指摘しているようにIEnumerable、.NET 4 でのみ共変になりました。次のようなコードを記述しようとしています。

IEnumerable<Object> strings = new List<string>();

.NET 4 以降のバージョンではコンパイルされますが、以前のバージョンではコンパイルされません。

于 2012-09-14T12:28:19.757 に答える
7

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?)

これは、標準インターフェイスではできないのに対し、共変インターフェイスではより多くの派生インスタンスが許可されるためです。

ここでフィドル

于 2012-09-14T12:46:46.577 に答える
6

共分散。これにより、ジェネリック パラメータで指定されたものよりも具体的なタイプまたは派生タイプのアイテムをコレクションに割り当てることができます。

IEnumerable<T>常に共変ではありませんでした。これは .NET 4 の新機能であり、変更の理由はこちらで説明されています。

于 2012-09-14T12:28:05.147 に答える
0

これを達成するには:

class Base {}
class Derived : Base {}

List<Derived> list = new List<Derived>();
IEnumerable<Base> sequence = list;
于 2012-09-14T12:28:32.960 に答える