我在 MSDN: 中看到过这种语法yield break
,但我不知道它的作用。有人知道吗?
8 回答
它指定迭代器已经结束。您可以将其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>
方法在之后立即重新获得控制权,所有局部变量的值与放弃控制权之前的值相同。
yield break
就像一个线程到达其功能的末尾并终止。
人们谈论“状态机”,但状态机实际上就是“线程”。一个线程有一些状态(即局部变量的值),每次调度它都会采取一些动作来达到一个新的状态。关键yield
在于,与我们习惯的操作系统线程不同,使用它的代码会及时冻结,直到手动推进或终止迭代。
yield break 只是表示最后一次返回并且不返回任何值的一种方式
例如
// 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 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(..)
.
这里http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/是一个很好的例子:
公共静态 IEnumerable<int> Range(int min, int max) { 而(真) { 如果 ( 最小值 >= 最大值 ) { 产量中断; } 收益返回 min++; } }
和解释,如果一个yield break
语句在一个方法中被命中,该方法的执行将停止并且没有返回。有一些时间情况,当你不想给出任何结果时,你可以使用yield break。
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。