コレクションの列挙処理
更新 : 2007 年 11 月
.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 が呼び出されるまで、同じオブジェクトを返します。MoveNext は Current を次の要素に設定します。
MoveNext が、コレクションの最後を越えた場合、列挙子はコレクションの最後の要素より後に位置することになり、MoveNext は false を返します。また、列挙子がこの位置になってからの MoveNext の呼び出しにも、false が返されます。最後の MoveNext の呼び出しで false が返されている場合の Current は未定義です。
非ジェネリック コレクションでは、MoveNext を呼び出した後に Reset を呼び出して、列挙子をコレクションの開始位置に戻すことができます。
ジェネリック コレクションの場合、Current を再びコレクションの最初の要素に設定することはできません。代わりに新しい列挙子インスタンスを作成する必要があります。
列挙子は、対応するコレクションが変更されない限り、有効です。コレクションに要素の追加、変更、削除などの変更が加えられると、列挙子は無効になって再び有効にできなくなり、その動作については定義されていません。
列挙子には、コレクションへの排他アクセスがありません。したがって、コレクションの列挙処理は本質的にスレッド セーフな処理ではありません。列挙処理を確実にスレッド セーフに行うには、列挙中にコレクションをロックします。コレクションに対し複数のスレッドがアクセスして読み取りや書き込みを行えるようにするには、独自の同期化を実装する必要があります。