イテレーターメソッドの結果を次のイテレーターメソッドにつなげるような呼び出しを行うと、イテレーターは全体で1回だけ実行される(遅延評価される)。
public static void Main(string[] args)
{
var nums = new[] {1, 2, 2, 3};
foreach (var num in Square(Unique(nums)))
{
WriteLine(num);
}
}
public static IEnumerable<T> Unique<T>(IEnumerable<T> sequence)
{
var uniqueVals = new HashSet<T>();
foreach (var item in sequence)
{
WriteLine($"Unique: {item.ToString()}");
if (uniqueVals.Contains(item)) continue;
uniqueVals.Add(item);
yield return item;
}
}
public static IEnumerable<int> Square(IEnumerable<int> nums)
{
foreach (var num in nums)
{
WriteLine($"Square: {num.ToString()}");
yield return num * num;
}
}
上記コードを実行すると、その出力は以下のようになる。「{1, 2, 2, 3}」という配列を前から順に1回だけ走査していることがわかる。
Unique: 1
Square: 1
1
Unique: 2
Square: 2
4
Unique: 2
Unique: 3
Square: 3
9
このように、イテレーターメソッドを使うと、通常のループに比べて、関数を合成するような使い方ができる。