『究極の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は予約語ではない。