views:

308

answers:

4

Can somebody tell me why compiler thinks that break is necessary after yield return in the following code?

    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;
        }
    }
A: 

presumably you're in an IEnumerator which will return to the statement following your yield. If not, can you provide full context?

No Refunds No Returns
+18  A: 

Because yield return is just syntactic sugar for an iterator generator, and you're not actually exiting any method. And C# doesn't allow fall-through in switch statements (and it doesn't look like you want it here anyway).

Matthew Flaschen
+2  A: 
Anders Abel
+8  A: 

Why break is required after return yield in a switch statement?

The question supposes an incorrect premise. A break statement is not required after a yield return in a switch statement. For example:

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

Here we have a yield return in a switch statement which is not followed by a break. It is followed by a call to M(), and then a throw statement. That's perfectly legal.

The real rule is that the end point of a switch section must not be reachable.

The end points of a break, continue, return, goto, return and throw are not reachable because all of those statements branch to another location and do not come back, so that the code token immediately following them is not reachable. This is in contrast with, say, a method call, which branches to another location and then comes back, or a yield return, which transfers control back to the caller; when the caller transfers control back to the iterator block, control will pick up where the yield return left off, so therefore the end point of the yield return is reachable.

If this subject interests you, I recommend reading section 8.1 of the specification.

Eric Lippert
Thank you for the detailed explanation. I am sorry for not being celar enough with my question. The concept of 'end of a switch section must not be reachable' is very clear to me. My confusion was about yield return - for some reason I thought that it branches out the same way the regular return does. I was wrong - mea culpa
mfeingold