什么是“收益中断”,在C#中做?
我在MSDN中看到了这个语法: yield break
,但是我不知道它是干什么的。 有人知道吗?
它指定迭代器已经结束。 您可以将yield break
作为不返回值的return
语句。
例如,如果将函数定义为迭代器,则函数的主体可能如下所示:
for (int i = 0; i < 5; i++) { yield return i; } Console.Out.WriteLine("You will see me");
请注意,循环完成所有循环后,最后一行会被执行,您将在控制台应用程序中看到消息。
或者像这样的yield break
:
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中没有更多的元素)。
告诉迭代器它已经到了最后。
举个例子:
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; } }
yield
基本上使一个IEnumerable<T>
方法的行为类似于合作(而不是预先)预定的线程。
yield return
就像是调用“时间表”或“睡眠”函数来放弃对CPU的控制。 就像一个线程, IEnumerable<T>
方法立即重新获得控制权,所有局部variables具有与控制权被放弃之前相同的值。
yield break
就像是一个到达其function和终止的线程。
人们谈论的是一个“状态机”,但是一个状态机确实是一个“线程”。 一个线程有一些状态(即局部variables的Ie值),并且每次调度它都会采取一些行动来达到一个新的状态。 关于yield
的关键点是,与我们习惯的操作系统线程不同,使用它的代码会被冻结,直到迭代被手动提前或终止。
Jon Skeet的书C#深入这个免费样本章节中 ,覆盖了迭代器块的整个主题。
这里http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/是非常好的例子:;
公共静态IEnumerable <int>范围(int min,int max) { 而(真) { 如果(min> = max) { 产量突破 } 产量回报最小值++; } }
并解释,如果一个方法内部命中一个yield break
语句,该方法的执行就会停止而不返回。 有一些时间情况,当你不想给出任何结果,那么你可以使用收益率突破。
如果你的意思是“什么是真正的收益中断”,那么“它是如何工作的” – 详见Raymond Chen的博客http://blogs.msdn.com/oldnewthing/archive/2008/08/12/8849519。; ASPX
C#迭代器生成一些非常复杂的代码。
yield break
语句导致枚举停止。 实际上, yield break
完成枚举而不返回任何附加项目。
考虑一下迭代器方法实际上有两种方法可以停止迭代。 在一种情况下,该方法的逻辑可以在返回所有项目后自然退出该方法。 这里是一个例子:
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."); }
在上面的例子中,一旦findmaxCount
素数,迭代器方法自然会停止执行。
yield break
语句是迭代器停止枚举的另一种方法。 这是一个早点摆脱枚举的方法。 这里是与上面相同的方法。 这一次,该方法对该方法可以执行的时间量有限制。
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."); }
注意打电话yield break
。 实际上,它早就退出了列举。
还要注意, yield break
作用不同于简单的break
。 在上面的例子中, yield break
在不调用Debug.WriteLine(..)
情况下退出该方法。
yield关键字与return关键字一起使用,为枚举器对象提供一个值。 yield return指定返回的值或值。 当yield yield return语句到达时,当前位置被存储。 下一次调用迭代器时,将从此位置重新启动执行。
用一个例子来解释含义:
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。
注意在这个例子中计数器variables是一个局部variables是很重要的。 在第二次迭代返回值2之后,第三次迭代从之前离开的位置开始,同时保留名为counter的局部variables为2的前一个值。