IEnumerableとIEnumeratorを使用していましたが、1つのポイントを明確に取得できませんでした。foreachがある場合、なぜこの2つのインターフェイスが必要なのですか?インターフェイスを使用する必要があるシナリオはありますか?はいの場合、誰かが例を挙げて説明できますか?任意の提案や意見を歓迎します。ありがとう。
foreach
ses多くの場合インターフェース。 implementforeach
が使用できるシーケンスを実行する場合はインターフェイスが必要です。 (ただし、イテレータブロックは通常、この実装タスクを非常に単純にします。)
ただし、ときどきイテレータを直接使用すると便利な場合があります。良い例は、2つの異なるシーケンスを「ペアリング」しようとする場合です。たとえば、名前と年齢の2つのシーケンスを受け取り、2つを一緒に印刷するとします。あなたは書くかもしれません:
static void PrintNamesAndAges(IEnumerable<string> names, IEnumerable<int> ages)
{
using (IEnumerator<int> ageIterator = ages.GetEnumerator())
{
foreach (string name in names)
{
if (!ageIterator.MoveNext())
{
throw new ArgumentException("Not enough ages");
}
Console.WriteLine("{0} is {1} years old", name, ageIterator.Current);
}
if (ageIterator.MoveNext())
{
throw new ArgumentException("Not enough names");
}
}
}
同様に、最初の項目を他の項目とは異なる方法で処理する(たとえば)場合は、イテレータを使用すると便利です。
public T Max<T>(IEnumerable<T> items)
{
Comparer<T> comparer = Comparer<T>.Default;
using (IEnumerator<T> iterator = items.GetEnumerator())
{
if (!iterator.MoveNext())
{
throw new InvalidOperationException("No elements");
}
T currentMax = iterator.Current;
// Now we've got an initial value, loop over the rest
while (iterator.MoveNext())
{
T candidate = iterator.Current;
if (comparer.Compare(candidate, currentMax) > 0)
{
currentMax = candidate;
}
}
return currentMax;
}
}
ここで、IEnumerator<T>
とIEnumerable<T>
の違いに興味がある場合は、データベースの用語で考えてみてください。IEnumerable<T>
をテーブル、IEnumerator<T>
カーソルとして。テーブルに新しいカーソルを与えるように依頼することができ、同じテーブル上に同時に複数のカーソルを置くことができます。
この違いを実際に理解するには時間がかかる場合がありますが、リスト(または配列など)には「リストのどこにいるか」という概念はなく、そのリスト/配列/その他のイテレータがあることを覚えておいてください。 doesその状態のビットが役立ちます。
ジョンが言ったこと。
IEnumerable
またはIEnumerable<T>
:これを実装することにより、オブジェクトは、シーケンス/コレクション/セットをトラバースするために使用できるイテレータを提供できることを示しますIEnumerator
またはIEnumerator<T>
:前のインターフェースで定義されたGetEnumeratorメソッドを呼び出すと、IEnumerator参照としてイテレーターオブジェクトを取得します。これにより、MoveNext()を呼び出して、Currentオブジェクトを取得できます。foreach
:内部でどのように機能するかを知る必要がないという意味で、C#コンストラクト/ファサードです。内部的にイテレータを取得し、適切なメソッドを呼び出して、各アイテム(foreachブロックのコンテンツ)で何をしたいかに集中します。ほとんどの場合、独自のタイプまたはカスタム反復を実装している場合を除き、foreachが必要です。実装している場合は、最初の2つのインターフェイスについて理解する必要があります。あなたはしないことを覚えておいてください 持ってる foreach --IIRCを使用するIEnumeratorとそのバリアントを実装するために必要なのは、boolを返すMoveNext()メソッドを持つオブジェクトを返すGetEnumerator()メソッドと、オブジェクトを返すCurrentプロパティだけです。 IEnumeratorとIEnumerableを使用する必要はありませんが、通常は使用することをお勧めします。詳細については、 ここ を参照してください。