基本的に、.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>
ないことに注意してください。これは、そうすることは型安全性が低いためです...一方、ジェネリックイテレータは、任意の値をに(ボクシングの可能性がある)変換し、コレクションに値を追加できるため、非ジェネリックイテレータと見なすことができます。そして、(たとえば)文字列をに追加することは意味がありません。ICollection
object
IList
ICollection
IList<int>
編集:私たちが必要とする理由はIEnumerable<T>
、タイプセーフな方法で反復し、その情報を伝播できるようにするためです。私があなたに返すIEnumerable<string>
場合、あなたはそれから返されるすべてが文字列参照またはnullであると安全に想定できることを知っています。を使用すると、のプロパティはタイプだけであるため、シーケンスから返された各要素IEnumerable
を効果的にキャストする必要がありました(多くの場合、ステートメントで暗黙的に) 。なぜまだ必要なのかというと、基本的に古いインターフェースがなくなることはないからです。それを使用している既存のコードが多すぎます。foreach
Current
IEnumerator
object
IEnumerable
IEnumerable<T>
拡張しないことは可能でしたIEnumerable
が、それを利用したいコードは、IEnumerable<T>
受け入れるメソッドを呼び出すことができませんでしたIEnumerable
-そして、.NET1.1および1.0からのそのようなメソッドがたくさんありました。