为什么在switch语句中返回yield后需要中断?

mfe*_*old 24 c# break switch-statement yield-return

有人可以告诉我为什么编译器认为在以下代码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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*hen 29

因为yield返回只是迭代器生成器的语法糖,并且您实际上并没有退出任何方法.并且C#不允许在switch语句中出现问题(并且它看起来并不像你想要的那样).


Eri*_*ert 17

为什么在switch语句中返回yield之后需要中断?

这个问题假设一个不正确的前提.break语句不能在switch语句中产量恢复后需要.例如:

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

这里我们在switch语句中有一个yield return,后面没有中断.接下来是对M()的调用,然后是一个throw语句.这完全合法.

真正的规则是切换部分的终点不能被访问.

break,continue,return,goto,return和throw的结束点是不可达的,因为所有这些语句都分支到另一个位置并且不会返回,因此紧跟在它们之后的代码令牌是不可访问的.这与例如方法调用形成对比,方法调用分支到另一个位置然后返回,或者产生返回,它将控制权转移回调用者; 当调用者将控制权转移回迭代器块时,控制将获取收益率返回的位置,因此收益率返回的终点是可达的.

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