質問

これは古い質問かもしれません:なぜ IEnumerable< T> IEnumerable を継承するのですか?

これは.NETの動作ですが、少し面倒です。クラスを書くたびに IEumerable< T> を実装するたびに、 IEnumerable< T> IEnumerable のもう1つ。

そして、 IList< T> はIListを継承しません。

IEnumerable< T> が他の方法で設計されている理由がわかりません。

役に立ちましたか?

解決

馬の口からの直線(Hejlsberg) :

  

理想的には、すべてのジェネリックコレクションインターフェイス(例: ICollection< T> IList< T> )は、ジェネリックインターフェイスインスタンスができるように、非ジェネリックの対応物から継承します。汎用コードと非汎用コードの両方で使用されます。たとえば、 IList< T> IList を予期するコードに渡すことができれば便利です。

     

結局のところ、これが可能な唯一の汎用インターフェイスは IEnumerable&lt; T&gt; です。これは、 IEnumerable&lt; T&gt; のみが反変であるためです:In < code> IEnumerable&lt; T&gt; 、型パラメーターTは&quot; output&quot;でのみ使用されます。 「入力」ではなく、位置(戻り値)。位置(パラメーター)。 ICollection&lt; T&gt; および IList&lt; T&gt; は、入力位置と出力位置の両方でTを使用するため、これらのインターフェイスは不変です。 (余談ですが、Tが入力位置でのみ使用された場合、それらは反変でしたが、それは実際にはここでは重要ではありません。)

     

&lt; ... snip ...&gt;

つまり、質問に答えるために、 IEnumerable&lt; T&gt; IEnumerable を継承しています。 :-)

他のヒント

IEnumerable の答えは、「型の安全性に影響を与えずにできるから」です。

IEnumerable は「読み取り専用」ですインターフェース-ジェネリック形式が非ジェネリック形式よりも具体的であることは重要ではありません。両方を実装しても何も壊れません。 IEnumerator.Current object を返しますが、 IEnumerator&lt; T&gt; .Current T を返します。常に合法的に object に変換しますが、ボクシングを意味する場合があります。

これを IList&lt; T&gt; および IList と比較します- IList Add(object)を呼び出すことができます>、それは特定の IList&lt; T&gt; (実際には IList&lt; object&gt; 以外のもの)では無効かもしれません。

Brad Abramの Andersの回答をブログに掲載このまさに質問。

下位互換性のためです。バニラIEnumerableを期待する.Net 1.1関数を呼び出す場合、ジェネリックIEnumerableを渡すことができます。

Luckillyは、一般的なIEnumeratorが古いスタイルのIEnumeratorから継承します

通常、列挙子を返すプライベートメソッドを実装し、古いスタイルと新しいスタイルの両方のGetEnumeratorメソッドに渡します。

    private IEnumerator<string> Enumerator() {
        // ...
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return Enumerator();
    }

これは、ジェネリックをサポートしないクラスで動作するようにするためです。さらに、.NETジェネリックでは、キャストIList&lt; long&gt;などを実行できません。 IList&lt; int&gt;のように、固定の基本クラスまたはインターフェイスが必要な場合、インターフェイスの非ジェネリックバージョンは非常に便利です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top