对于迭代器方法中的每个循环

时间:2015-01-23 10:38:18

标签: c# .net foreach iterator unreachable-code

查看此计划:

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函数。
这种行为有什么解释?

Check it out for yourself

3 个答案:

答案 0 :(得分:3)

迭代器块是懒惰的。您需要通过在foreach或其他内容中调用它来调用它。迭代器块中的代码仅在第一次调用MoveNext foreach将为您执行时执行。

截至目前,您只是准备查询,您需要通过调用GetEnumerator后跟MoveNext来实现该问题。

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

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

进一步阅读Iterator block implementation details

答案 1 :(得分: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;
}

答案 2 :(得分:1)

这是因为懒惰的执行。尝试使用您的功能结果,例如:

GetLinks().First();