C#では2.0より、VBではVB11(VB2012)よりイテレータ構文が導入されています。 これはIEnumerator<T>(またはIEnumerable)の実装をより簡単に記述できるものです。 C#ではyield
キーワード、VBではYield
ステートメントを用いることでイテレータを実装することができます。
イテレータ (反復子)
イテレータがどのようなものか具体的な例を見てみます。
このようにイテレータ構文を使うとIEnumerable・IEnumeratorを実装しなくても列挙ができるようになっています。 C#ではyield return 値
、VBではYield 値
とすることで列挙される値を返すことができます。 VBでは、イテレータとなるメソッドにIterator
修飾子を付ける必要があります。
もうひとつ違いと相違点を明らかにするための別の例を挙げます。 イテレータとIEnumerable・IEnumeratorのそれぞれで同じ要素を列挙するクラスを実装すると次のようになります。 (ここでは記述をシンプルにするためにIEnumerable<T>ではなく非ジェネリックなIEnumerableを実装しています)
イテレータを使ったコードでは、コンパイル時にCurrentプロパティやMoveNextメソッドなどIEnumerator(またはIEnumerator<T>)に必要なメンバが自動的に実装されます。
遅延実行
イテレータの動作はIEnumerable<T>
を実装した場合と変わりないように見えますが、異なる動作となる部分もあります。
この結果を見ると普通にListなどを列挙する場合と変わらないように見えますが、yield
は結果が生成されるタイミングが違います。 GenerateNumbers
メソッドを次のように変えてyield
が実行されるタイミングを調べてみると違いが明らかになります。
この動作は遅延実行と呼ばれるものです。 通常のメソッドとは異なり、イテレータとなるメソッドでは呼び出された時点でIEnumerable
が返されるものの、イテレータメソッド内のyield
文は実際に値が列挙されるまでは呼び出されません。
イテレータ実装時の注意点
イテレータ構文は、戻り値の型がIEnumerable
(IEnumerable<T>
)もしくはIEnumerator
(IEnumerator<T>
)であるメソッドまたはプロパティで記述することができます。
ただし、匿名メソッドでは使用できない、例外処理に制限があるなど、イテレータ構文特有の注意点があります。 詳細は反復子 (C# プログラミング ガイド)を参照してください。