前回は、配列が持っているGetEnumeratorメソッドでIEnumeratorを返すことができた・・・。
IEnumerator インターフェイス (System.Collections)
IEnumeratorは、C++でいうイテレータで、コレクションの次の要素の取出しをするためのインターフェイス・・・。
今回は、これを継承したクラスを実装して、GetEnumeratorで返す・・・。
int配列の参照container、サイズのlength、現在位置(正確には+1)を持つindexを用意・・・。
Currentプロパティのgetで、index-1の指しているオブジェクトを返す・・・。
コンストラクタは渡された配列con、サイズlenをセットし、indexは0に・・・。
MoveNextでは、1つindexを増やし、indexが範囲内ならtrue、そうでないならfalseを返す・・・。
これまで、index-1としているが、これはforeachが、
IEnumerator enumerator = collection.GetEnumerator(); while (enumerator.MoveNext()) { object obj = enumerator.Current; }
このように、enumerator.MoveNext()を最初に呼ぶ前方評価で取り出しているせいでこうなっている・・・。
※.最初はindexでつくったが、おかしいとおもったら、foreachはそういう仕様らしい・・・。後方評価のほうがindexですっきりするのに・・・。
だから、indexは内部では1から始まるが、外から配列にアクセスするときは0からになるようにしている・・・。
今回Resetは使わない・・・。
このようなインターフェイスを使うことで、どんなコレクションでも取り出せる(今回はint配列だけだが・・・。)
TestCollection.csは、
collection本体はこちらでもっている・・・。
collectionをこちらで生成して、testEnumeratorにcollectionとサイズlenを渡してる・・・。
IEnumeratorは列挙しかできないので、個別の値のセットはインデクサで・・・。
testCollectionをサイズ5で生成し、4, 2, 1, 3, 5という感じで値をセット・・・。
foreachで取り出すと、
GetEnumerator() MoveNext, index = 0 index = 0, Current = 4 value = 4 MoveNext, index = 1 index = 1, Current = 2 value = 2 MoveNext, index = 2 index = 2, Current = 1 value = 1 MoveNext, index = 3 index = 3, Current = 3 value = 3 MoveNext, index = 4 index = 4, Current = 5 value = 5 続行するには何かキーを押してください . . .
このように出力される・・・。
foreachの、
foreach (int value in testCollection)
ここでGetEnumeratorが呼ばれて、IEnumerator操作のできるオブジェクトが生まれている・・・。
あとはループするごとに、MoveNextとCurrentが呼ばれる・・・。
Sample/dotnet/IEnumerator/IEnumerator/src/IEnumerator_ at master · bg1bgst333/Sample · GitHub