『究極のC#プログラミング』Chapter3 yield returnとForEach その1
for文で数を数える時に
for(i = 0; i <= 9; j++) // iでなくj { // code }
というミスがありうる。これを回避するのがforeachであり、
foreach(T elem1 in Obj1) { // code }
のように変数を一箇所だけ使って書ける。
しかし、列挙可能なオブジェクトを作るのがC# 1.xでは面倒だった。
これを解決するのがC# 3.0の反復子である。
ちなみにRubyでは
for i in 0..9 // code end
と書ける
.NET Framework 3.5のSystem.Linq.Enumerable.Rangeメソッドを使うと、
foreach(int i in Enumerable.Range(0, 10)) { // code }
と書ける。
以下では、
foreach(int i in new Range(0, 9)) { // code }
と書けるRangeクラスの実装を考える。
C# 1.xとC# 3.0でのRangeクラスの実装
C# 1.xでの2つの欠点
・RangeクラスとRangeEnumクラス(Rangeクラスのenumerator)の2つを書く必要があって面倒。
・そのRangeEnumクラスには、IEnumerable(+その他の列挙関係のインターフェース)を実装する必要があり面倒。
C# 3.0だとこう書ける
class Range { private int from, to; public IEnumerator<int> GetEnumerator() { for(int i = from; i <= to; i++) yield return i; } public Range(int from, int to) { this.from = from; this.to = to; } }
yield return, yield breakを含むブロックは、反復子ブロックと呼ぶ。
このブロックは、すぐには実行されず列挙子オブジェクトが生成されて、foreach文で列挙が開始された時に実行される。
実行するたびに次のyield returnのところまで実行されて、値が返される。
yieldは予約語ではない。