24

有人能告诉我为什么编译器在下面的代码中认为这break是必要的吗?yield return

foreach (DesignerNode node in nodeProvider.GetNodes(span, node => node.NodeType != NDjango.Interfaces.NodeType.ParsingContext))
{
    switch (node.ErrorMessage.Severity)
    {
        case -1:
        case 0:
            continue;
        case 1:
            yield return new TagSpan<ErrorTag>(node.SnapshotSpan, new ErrorTag(PredefinedErrorTypeNames.Warning));
            break;
        default:
            yield return new TagSpan<ErrorTag>(node.SnapshotSpan, new ErrorTag(PredefinedErrorTypeNames.SyntaxError));
            break;
    }
}
4

3 回答 3

31

因为 yield return 只是迭代器生成器的语法糖,你实际上并没有退出任何方法。并且 C# 不允许在switch语句中出现故障(而且看起来你也不想要它)。

于 2010-03-01T19:50:01.870 回答
17

为什么在 switch 语句中 return yield 后需要 break?

这个问题假设了一个不正确的前提。在 switch 语句中的 yield return 之后不需要break语句。例如:

switch(x)
{
case 123:
    yield return 456;
    M();
    throw new Exception();
case 789: // and so on

在这里,我们在 switch 语句中有一个收益返回,它后面没有中断。接着是对 M() 的调用,然后是 throw 语句。这是完全合法的。

真正的规则是开关部分的端点不能到达

无法到达 break、continue、return、goto、return 和 throw 的端点,因为所有这些语句都分支到另一个位置并且不会返回,因此无法到达紧随它们之后的代码标记。这与例如方法调用相反,它分支到另一个位置然后返回,或者返回返回,它将控制权转移回调用者;当调用者将控制权转移回迭代器块时,控制权将在 yield return 停止的地方重新开始,因此 yield return 的终点是可以到达的。

如果您对这个主题感兴趣,我建议您阅读规范的第 8.1 节。

于 2010-03-01T23:27:03.967 回答
2

“正常”返回有两个功能:

  1. 标记函数的返回值。
  2. 将控制权转移给调用者。

一个 yield 返回只标记一个返回值;它不影响控制流。在 yield return 语句之后,程序在下一行继续执行,在您的示例中需要中断,就像在任何其他 switch-case 语句中一样。

于 2010-03-01T19:52:46.763 回答