我在MSDN中看到过这种语法:yield break
,但我不知道它的作用。有谁知道吗?
答案 0 :(得分:485)
它指定迭代器已经结束。您可以将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");
在这种情况下,永远不会执行最后一个语句,因为我们提前离开了该函数。
答案 1 :(得分:51)
结束迭代器块(例如,IEnumerable中没有更多元素)。
答案 2 :(得分:29)
告诉迭代器它已到达终点。
举个例子:
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;
}
}
答案 3 :(得分:19)
yield
基本上使IEnumerable<T>
方法的行为类似于合作(而不是先发制人)预定的线程。
yield return
就像一个调用“schedule”或“sleep”函数的线程来放弃对CPU的控制。就像一个线程一样,IEnumerable<T>
方法会立即重新获得控制,所有局部变量都具有与放弃控制之前相同的值。
yield break
就像一个线程到达其功能的末尾并终止。
人们谈论的是“状态机”,但状态机实际上是一个“线程”。线程具有一些状态(即局部变量的值),并且每次调度它都需要一些操作才能达到新状态。关于yield
的关键点是,与我们习惯使用的操作系统线程不同,使用它的代码会被及时冻结,直到迭代被手动提前或终止。
答案 4 :(得分:10)
在Jon Skeet的书free sample chapter中C# in Depth中详细介绍了迭代器块的整个主题。
答案 5 :(得分:7)
这里http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/是一个非常好的例子:
public static IEnumerable<int> Range( int min, int max ) { while ( true ) { if ( min >= max ) { yield break; } yield return min++; } }
并解释说,如果在方法中遇到yield break
语句,则该方法的执行将停止而不返回。有一些时间情况,当你不想给出任何结果时,你可以使用yield break。
答案 6 :(得分:5)
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.");
}
在上面的例子中,迭代器方法在找到maxCount
素数后自然会停止执行。
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(..)
。
答案 7 :(得分:4)
如果你的意思是“什么让收益突破呢?”,“它是如何运作的” - 请参阅Raymond Chen的博客了解详情http://blogs.msdn.com/oldnewthing/archive/2008/08/12/8849519.aspx
C#迭代器生成一些非常复杂的代码。
答案 8 :(得分:3)
收益率突破只是最后一次回报的一种方式,不返回任何值
例如
// 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;
}
答案 9 :(得分:-2)
yield关键字与return关键字一起使用,为枚举器对象提供值。 yield return 指定返回的值。达到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。
重要的是要注意,此示例中的计数器变量是局部变量。在第二次迭代后返回值2,第三次迭代从它离开的位置开始之前,同时保留名为 counter 的局部变量的前一个值,该值为2。