2

看看这个程序:

static class Program
{
  static void Main()
  {
    GetLinks();
    Console.WriteLine("Program failed!");
  }

  static IEnumerable<string> GetLinks()
  {
    throw new Exception();
    foreach (var item in new string[] { })
      yield return item;
  }
}

这很奇怪,但是这个程序的结果是Program failed!,这意味着该GetLinks函数甚至没有被调用。
这种行为的解释是什么?

自己检查一下

4

3 回答 3

3

迭代器块是惰性的。您需要通过在 aforeach或其他东西中调用它来调用它。迭代器块中的代码只会在第一次调用时执行,MoveNextforeach将为您执行。

到目前为止,您只是在准备查询,您需要通过调用来实现它,然后GetEnumerator调用MoveNext.

例如,以下代码将按预期失败。

static void Main()
{
    foreach(var item in GetLinks())
        Console.WriteLine(item );
    Console.WriteLine("Program failed!");
}

进一步阅读迭代器块实现细节

于 2015-01-23T10:40:50.160 回答
3

迭代器块是一种有点特殊的方法......当它看到yield return关键字时,编译器会生成一个实现IEnumerator<T>(并且还IEnumerable<T>取决于您的方法的返回类型)的类,并更改您的方法以返回此类的实例。您方法的原始主体被转换为MoveNext枚举器的方法。这意味着您的方法的主体仅在枚举结果时执行。如果您不枚举结果,则仅调用该方法无效。换句话说,迭代器块是延迟执行的。

这就是为什么作为迭代器块实现的方法必须在单独的方法中验证它们的参数:

public IEnumerable<string> Foo(string arg)
{
    if (arg == null) throw new ArgumentNullException();
    return FooIterator(arg);
}

private IEnumerable<string> FooIterator(string arg)
{
    yield return arg;
}
于 2015-01-23T10:45:09.310 回答
1

这是因为延迟执行。尝试使用函数的结果,例如:

GetLinks().First();
于 2015-01-23T10:41:03.067 回答