What does “yield break;” do in C#?
我在msdn中见过这个语法:
它指定迭代器已经结束。您可以将
例如,如果将函数定义为迭代器,则函数体可能如下所示:
1 2 3 4 5 6 | for (int i = 0; i < 5; i++) { yield return i; } Console.Out.WriteLine("You will see me"); |
请注意,在循环完成所有循环后,最后一行将被执行,您将在控制台应用程序中看到该消息。
或者像这样用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | int i = 0; while (true) { if (i < 5) { yield return i; } else { // note that i++ will not be executed after this yield break; } i++; } Console.Out.WriteLine("Won't see me"); |
在这种情况下,不会执行最后一条语句,因为我们提前离开了函数。
结束迭代器块(例如说IEnumerable中没有其他元素)。
告诉迭代器它已到达末尾。
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public interface INode { IEnumerable<Node> GetChildren(); } public class NodeWithTenChildren : INode { private Node[] m_children = new Node[10]; public IEnumerable<Node> GetChildren() { for( int n = 0; n < 10; ++n ) { yield return m_children[ n ]; } } } public class NodeWithNoChildren : INode { public IEnumerable<Node> GetChildren() { yield break; } } |
人们谈论的是"状态机",但状态机其实都是"线程"。线程有一些状态(即局部变量的值),每次调度线程时,它都会采取一些操作以达到新的状态。关于
迭代器块的整个主题在乔恩·斯基特的书C中的这个自由示例章节中有很好的介绍。
这里http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/就是一个很好的例子:
1 2 3 4 5 6 7 8 9 10 11 | public static IEnumerable<int> Range( int min, int max ) { while ( true ) { if ( min >= max ) { yield break; } yield return min++; } } |
并且解释说,如果在一个方法中命中一个
考虑到迭代器方法实际上有两种方法可以停止迭代。在一种情况下,该方法的逻辑可以在返回所有项之后自然地退出该方法。下面是一个例子:
1 2 3 4 5 6 7 8 9 10 | IEnumerable<uint> FindPrimes(uint startAt, uint maxCount) { for (var i = 0UL; i < maxCount; i++) { startAt = NextPrime(startAt); yield return startAt; } Debug.WriteLine("All the primes were found."); } |
在上面的示例中,一旦找到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | IEnumerable<uint> FindPrimes(uint startAt, uint maxCount, int maxMinutes) { var sw = System.Diagnostics.Stopwatch.StartNew(); for (var i = 0UL; i < maxCount; i++) { startAt = NextPrime(startAt); yield return startAt; if (sw.Elapsed.TotalMinutes > maxMinutes) yield break; } Debug.WriteLine("All the primes were found."); } |
注意对
也要注意,
如果你所说的"产量突破真正起作用的是什么",那就是"它是如何起作用的"—有关详细信息,请参阅Raymond Chen的博客:http://blog s.msdn.com/oldnewthing/archive/2008/08/12/8849519.aspx
C迭代器生成一些非常复杂的代码。
收益率突破只是最后一次说回报的一种方式,不返回任何价值。
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // returns 1,2,3,4,5 IEnumerable<int> CountToFive() { yield return 1; yield return 2; yield return 3; yield return 4; yield return 5; yield break; yield return 6; yield return 7; yield return 8; yield return 9; } |
yield关键字与return关键字一起使用,为枚举器对象提供一个值。yield return指定返回的值。当到达Yield RETURN语句时,将存储当前位置。下次调用迭代器时,将从此位置重新启动执行。
用一个例子解释其含义:
1
2
3
4
5
6
7
8
9
10
11
12
13 public IEnumerable<int> SampleNumbers()
{
int counter = 0;
yield return counter;
counter = counter + 2;
yield return counter;
counter = counter + 3;
yield return counter ;
}
迭代时返回的值为:0、2、5。
需要注意的是,本例中的计数器变量是局部变量。在返回值2的第二次迭代之后,第三次迭代从它离开之前的位置开始,同时保留名为counter的局部变量以前的值2。