关于c#:Yield如何在ForEach块中运行?


How Yield works within a ForEach block?

在下面所示的foreach循环中,产量是如何工作的?lstnumbers是List类型。

1
2
3
4
foreach (int i in lstNumbers)
{
    yield return i;
}

它是在接收到值时开始返回,还是在末尾返回最终列表?

它与以下有什么不同:

1
2
3
4
   foreach (int i in lstNumbers)
    {
        return i;
    }


在本例中,它将逐个返回所有值,但使用代码需要开始对结果集进行迭代:

1
2
3
4
foreach (int i in lstNumbers)
{
    yield return i;
}

请看下面的示例,该示例将在控制台上打印1, 2,如果消费代码不在可枚举的上迭代,则方法内部的for循环将永远不会结束:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        foreach (var item in Get().Take(2))
        {
            Console.WriteLine(item);
        }
    }

    static IEnumerable<int> Get()
    {
        foreach (var item in new[] { 1, 2, 3 })
        {
            yield return item;
        }
    }
}

在这种情况下,您可能不需要做出任何让步,只需返回结果,因为您已经拥有了它:

1
return lstNumbers;

在第二种情况下:

1
2
3
4
foreach (int i in lstNumbers)
{
    return i;
}

您只需返回列表的第一个值,迭代就会立即中断。


在第一种情况下,它只是在调用return i时返回i

调用方再次对函数调用迭代器之后,它将跳转到下一个迭代。

举例说明:

1
2
3
4
5
6
int GetNextNumber() {
  foreach (int in in lstNumbers)
  {
     yield return in;  //returns on first hit
  }
}

之后

1
2
3
4
5
foreach(var i in GetNextNumber()) {
     //process number got from the GetNextNumber()
     //on next iteration GetNextNumber() will be called again
     // so the next number from lstNumbers will be returned
}

这是处理长数据流的一种非常常见的方法,在这种方法中,您依次选择IT流程中的一部分,然后请求另一个流程,等等。

在第二种情况下,相反,您将始终返回列表中的第一个元素,并且永远不会跳转到其他元素。