58

IEnumerableとの違いは何IEnumerable<T>ですか?

これらのインターフェイスの両方を実装する多くのフレームワーククラスを見てきました。したがって、両方を実装することでどのような利点が得られるのか知りたいですか?

それらがどのように定義されているかを見てください:

public interface IEnumerable
{
    [DispId(-4)]
    IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

ご覧のとおり、IEnumerable<T>から派生します。つまり、持ってIEnumerableいるものは何でも継承します。それでは、なぜ、単にではなく両方を実装するのでしょうか。実装が不十分ですか?IEnumerableIEnumerable<T>IEnumerable<T>IEnumerable<T>

同様に、他の同様のペアがあります。

  • IListIList<T>
  • ICollectionICollection<T>

これらについても知りたいです。

4

4 に答える 4

67

基本的に、.NET 1.0および1.1では、非汎用インターフェイスが最初に登場しました。その後、.NET 2.0が登場すると、一般的な同等のものが登場しました。ジェネリックスが.NET1.0に組み込まれていれば、人生はずっと簡単だったでしょう:)

両方ではなく「のみ」を実装するという点では、IEnumerable<T>基本的に両方GetEnumeratorを実装する必要があり、両方がパラメータなしのメソッドを定義している場合は、明示的なインターフェイス実装も使用する必要があります。同様に、それIEnumerator<T>IEnumerator通常次のようなものです:

public IEnumerator<T> GetEnumerator()
{
    // Return real iterator
}

// Explicit implementation of nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
    // Delegate to the generic implementation
    return GetEnumerator();
}

一方、C#2で導入されたイテレータブロック(withyield returnなど)では、幸いなことに、これらを完全に手作業で実装する必要はほとんどありません。yield return上記のようなものを書いて、GetEnumeratorメソッドで使用する必要があるかもしれません。

拡張IList<T>IList、拡張しICollection<T>ないことに注意してください。これは、そうすることは型安全性が低いためです...一方、ジェネリックイテレータは、任意の値をに(ボクシングの可能性がある)変換し、コレクションに値を追加できるため、非ジェネリックイテレータと見なすことができますそして、(たとえば)文字列をに追加することは意味がありません。ICollectionobjectIListICollectionIList<int>

編集:私たちが必要とする理由はIEnumerable<T>、タイプセーフな方法で反復し、その情報を伝播できるようにするためです。私があなたに返すIEnumerable<string>場合、あなたはそれから返されるすべてが文字列参照またはnullであると安全に想定できることを知っています。を使用すると、のプロパティはタイプだけであるため、シーケンスから返された各要素IEnumerableを効果的にキャストする必要がありました(多くの場合、ステートメントで暗黙的に) 。なぜまだ必要なのかというと、基本的に古いインターフェースがなくなることはないからです。それを使用している既存のコードが多すぎます。foreachCurrentIEnumeratorobjectIEnumerable

IEnumerable<T>拡張しないことは可能でしたIEnumerableが、それを利用したいコードは、IEnumerable<T>受け入れるメソッドを呼び出すことができませんでしたIEnumerable-そして、.NET1.1および1.0からのそのようなメソッドがたくさんありました。

于 2011-02-11T17:34:37.677 に答える
10

1つはObject型のオブジェクトを返し、もう1つはT型のオブジェクトを返します。

于 2011-02-11T17:34:59.687 に答える
3

IEnumerable< T > は IEnumerable を実装していますが、両方を定義しているクラスが表示される理由については、必要ありませんが、自己文書化でサブインターフェイスをリストするのに適しています。検討

interface IA { }
interface IB : IA { }

class A : IB {} // legal, IB implements IA

class B : IA, IB {} // also legal, possible more clear on intent
于 2011-02-11T17:40:29.983 に答える
0

ループを反復処理している間、IEnumeratorは状態を維持します。カーソル位置を記憶しますが、IEnumerableは記憶しません。

于 2013-02-24T22:55:21.157 に答える