コレクションの列挙処理

.NET Framework には、コレクションを簡単に反復処理する手段として、列挙子が用意されています。 列挙子は、コレクション内のデータを読み取るためにだけ使用されます。列挙子を使用して、基になるコレクションを変更することはできません。

一部の言語では、列挙子を直接使用する際の複雑性を隠すステートメントが用意されています。 C# の foreach ステートメント、C++ の for each ステートメント、および Visual Basic の For Each ステートメントは列挙子を使用します。

列挙子の概要

列挙子はコレクションを平坦化し、そのコレクション内のメンバーに順次アクセスできるようにします。 コレクション クラスが異なれば、この順序も異なる場合があります。 たとえば、ArrayList の列挙子は、要素がコレクションに格納された順序を維持しますが、Hashtable の列挙子は、要素のハッシュ コードに従って要素を表示します。

すべての列挙子は、次のメンバーを必要とする IEnumerator インターフェイスまたは IEnumerator<T> ジェネリック インターフェイスに基づいています。

  • Current プロパティは、コレクション内の現在のメンバーを指します。

  • MoveNext プロパティは、列挙子をコレクション内の次のメンバーに移動します。

  • Reset プロパティは、列挙子をコレクションの先頭に戻します。 Current は、最初の要素の前に位置付けられます。 Reset は、IEnumerator<T> ジェネリック インターフェイスでは使用できません。

列挙子の動作

初期状態では、列挙子は、コレクションの最初の要素の前に位置付けられます。 また、Reset も、列挙子をこの位置に戻します。 この位置での Current は未定義です。 したがって、Current の値を読み取る前に、MoveNext を呼び出して、列挙子をコレクションの最初の要素の位置に進める必要があります。

Current は、MoveNext または Reset が呼び出されるまで、同じオブジェクトを返します。 MoveNextCurrent を次の要素に設定します。

MoveNext が、コレクションの最後を越えた場合、列挙子はコレクションの最後の要素より後に位置することになり、MoveNext は false を返します。 また、列挙子がこの位置になってからの MoveNext の呼び出しにも、false が返されます。 最後の MoveNext の呼び出しで false が返されている場合の Current は未定義です。

非ジェネリック コレクションでは、MoveNext を呼び出した後に Reset を呼び出して、列挙子をコレクションの開始位置に戻すことができます。

ジェネリック コレクションの場合、Current を再びコレクションの最初の要素に設定することはできません。代わりに新しい列挙子インスタンスを作成する必要があります。

コレクションが変更されない限り、列挙子は有効なままです。 要素の追加、変更、削除などの変更がコレクションに対して実行されると、列挙子は回復不可能な無効状態になり、動作は未定義になります。

列挙子はコレクションへの排他アクセス権を持たないため、コレクションの列挙処理は、本質的にはスレッド セーフな処理ではありません。 すべての列挙処理が終わるまでコレクションをロックすることにより、列挙処理でのスレッド セーフを確保できます。 コレクションに対し複数のスレッドがアクセスして読み取りや書き込みを行うことができるようにするには、独自の同期化を実装するか、System.Collections.Concurrent 名前空間のスレッド セーフなコレクション クラスのいずれかを使用する必要があります。 System.Collections.Concurrent.ConcurrentQueue<T> クラスと System.Collections.Concurrent.ConcurrentStack<T> クラスは、要素を列挙する前にそのスナップショットを取得し、別のスレッドのコレクションが変更されないようにします。 System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> クラスはスナップショットを取得しません。

System.Collections.Concurrent.BlockingCollection<T> クラスには、項目を列挙したらコレクションから削除することでコレクションを変更する GetConsumingEnumerable という名前の列挙子メソッドが用意されています。

参照

参照

IEnumerator

IEnumerator<T>

IDictionaryEnumerator

IEnumerable

IEnumerable<T>

その他の技術情報

コレクションの作成と操作

スレッド セーフなコレクション