読者です 読者をやめる 読者になる 読者になる

IEnumerator

前回は、配列が持っている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