34

可能重复:
“yield break”是什么意思?在 C# 中做?

任何人都可以看到使用“break”或“return”无法实现的“yield break”语句的用途。

这种说法似乎完全没有用。更重要的是,如果没有这个语句,“yield return X”语句可能会被简化为“yield X”,这样更易​​读。

我错过了什么?

4

6 回答 6

68

举一个代码示例,假设您要编写一个迭代器,如果源为 null 或为空,则该迭代器不返回任何内容。

public IEnumerable<T> EnumerateThroughNull<T>(IEnumerable<T> source)
{
    if (source == null)
        yield break;

    foreach (T item in source)
        yield return item;
}

如果没有 yield break,就不可能在迭代器中返回一个空集。

于 2009-01-31T01:04:38.080 回答
9

yield break 指定方法应该停止返回结果。“返回”本身不够好,甚至可能导致错误,因为方法的返回类型必须是 IEnumerable。

我不确定为什么还需要 return 关键字。我最好的猜测是它有助于使声明的意图更加清晰。

如果你有兴趣,这篇文章解释了 yield 在幕后做了什么

C# yield 关键字的幕后花絮

于 2009-01-31T00:29:57.807 回答
7

yield break 和 break 做完全不同的事情!看

for(int i = 0; i < 10; ++i) {
   if(i > 5) { break; }
   yield return i;
}

for(int v = 2710; v < 2714; v+=2) {
   yield return v;
}

for(int s = 16; s < 147; ++s) {
   if(s == 27) { yield break; }
   else if(s > 17) { yield return s; }
}

输出将是以下值的 IEnumerable:0、1、2、3、4、5、2710、2712、18、19、20、21、22、23、24、25、26

这是一些没有用的方法,但它说明您可以将 yield break 和 break 组合到同一个方法中,它们做了两件不同的事情!Break 只是跳出循环,yield break 完全结束方法。

我猜未使用 return 的原因是因为您没有在方法中自己返回 IEnumerable 。此外,对于这种迭代情况,您不认为 yield break 比 return 更清晰吗?我个人会。

于 2009-01-31T01:04:40.483 回答
3

return在迭代器块中使用语句是非法的。此外,break如果允许该语句影响迭代,则该语句可以在迭代器块中用于双重目的:它可以用于跳出循环或跳出开关,并且可以用于跳出整个迭代。

yield returnand yield breakand 本身就是两个关键字,它们似乎都是必要的。

于 2009-01-31T00:56:08.347 回答
0

您需要区分返回一个已经存在的 IEnumerable 实现(也许您将返回一个 List)和一个匿名迭代器。

您不能只使用 return 或 break,因为它们是可用于其他目的的有效关键字。您也不能单独使用yield,因为您需要有一种方法来指定是返回枚举中的项目还是结束枚举,因此需要yield return 和yield break。

于 2009-01-31T00:52:18.807 回答
0

return语句用于从函数返回值。

如果您有这样的迭代器函数:

public IEnumerable<int> IteratorOverInt() { }

上述函数中的 return 语句需要返回一个填充的IEnumerable<int>.

public IEnumerable<int> IteratorOverInt() {
    return new List<int> { 1, 2, 3, 4 };
}

但是如果您正在处理迭代器函数,您将使用yield return,因此您的代码可能如下所示:

public IEnumerable<int> IteratorOverInt() {
    for (int i = 0; i < 4; i++) {
        yield return i;
    }
}

方法签名要求yield return的返回时间也是如此intIEnumerable<int>

return在上述情况下,声明会做什么?返回结果覆盖收益率?将任何内容连接到收益率?return在上述情况下没有多大意义。

因此,我们需要一种return在迭代器块中有意义的方法,这就是为什么存在yield break.

当然你可以用 a 来做break,但是如果你有更多要执行的代码,你将如何退出函数体?将所有内容包装在一个复杂的 if-else 块中?我会说只是拥有yield break会更好。

于 2009-01-31T00:58:22.943 回答