懒惰的评价

只有当 foreach 语句移动到下一个项时,迭代器块才会计算到下一个 yield 语句。

请考虑以下示例:

private IEnumerable<int> Integers()
{
    var i = 0;
    while(true)
    {
        Console.WriteLine("Inside iterator: " + i);
        yield return i;
        i++;
    }
}

private void PrintNumbers()
{
    var numbers = Integers().Take(3);
    Console.WriteLine("Starting iteration");

    foreach(var number in numbers)
    {
        Console.WriteLine("Inside foreach: " + number);
    }
}

这将输出:

开始迭代迭代
器内部:0
内部 foreach:0
内部迭代器:1
内部 foreach:1
内部迭代器:2
内部 foreach:2

查看演示

作为结果:

  • 首先打印开始迭代,即使在行打印之前调用迭代器方法,因为行 Integers().Take(3); 实际上没有开始迭代(没有调用 IEnumerator.MoveNext()
  • 打印到控制台的行在迭代器方法内部和 foreach 内部的行之间交替,而不是迭代器方法内部的所有行首先评估
  • 这个程序由于 .Take() 方法而终止,即使迭代器方法有一个从未打破过的 while true