556

我在 MSDN: 中看到过这种语法yield break,但我不知道它的作用。有人知道吗?

4

8 回答 8

590

它指定迭代器已经结束。您可以将其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");

在这种情况下,最后一条语句永远不会执行,因为我们提前离开了函数。

于 2008-10-23T23:27:22.053 回答
63

结束一个迭代器块(例如,表示 IEnumerable 中没有更多元素)。

于 2008-10-23T23:09:09.577 回答
33

告诉迭代器它已经到达终点。

举个例子:

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;
    }
}
于 2008-10-23T23:17:00.623 回答
26

yield基本上使IEnumerable<T>方法的行为类似于协作(而不是抢占式)调度线程。

yield return就像一个线程调用“调度”或“睡眠”函数来放弃对 CPU 的控制。就像线程一样,该IEnumerable<T>方法在之后立即重新获得控制权,所有局部变量的值与放弃控制权之前的值相同。

yield break就像一个线程到达其功能的末尾并终止。

人们谈论“状态机”,但状态机实际上就是“线程”。一个线程有一些状态(即局部变量的值),每次调度它都会采取一些动作来达到一个新的状态。关键yield在于,与我们习惯的操作系统线程不同,使用它的代码会及时冻结,直到手动推进或终止迭代。

于 2009-06-26T20:33:37.653 回答
13

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;
 }
于 2018-07-24T15:13:03.043 回答
12

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(..).

于 2016-11-26T01:22:56.780 回答
8

这里http://www.alteridem.net/2007/08/22/the-yield-statement-in-c/是一个很好的例子:

公共静态 IEnumerable<int> Range(int min, int max)
{
   而(真)
   {
      如果 ( 最小值 >= 最大值 )
      {
         产量中断;
      }
      收益返回 min++;
   }
}

和解释,如果一个yield break语句在一个方法中被命中,该方法的执行将停止并且没有返回。有一些时间情况,当你不想给出任何结果时,你可以使用yield break。

于 2010-04-04T08:59:27.263 回答
-3

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。

于 2012-01-07T16:32:05.797 回答