3

As you might expect, this code produces a compiler error:

public static IEnumerable<int> Foo()
{
}

not all code paths return a value

However, this compiles with only a warning about unreachable code:

public static IEnumerable<int> Foo()
{
    if(false)
    {
        yield return 0;
    }
}

This produces an empty enumerable. Why does this work, and is it defined behavior?

StackOverthrow
  • 1,158
  • 11
  • 23
  • Wow, I give the c# compiler a lot of credit if this is actually the case. @mjwills – JamieT Jul 20 '19 at 00:01
  • 1
    @JamieTaylorSangerman It is almost the other way around. The compiler is quite stupid - it just says 'well, I see a yield return' by my understanding. It doesn't try and do excessive reachability analysis etc etc. – mjwills Jul 20 '19 at 00:02

1 Answers1

7
public static IEnumerable<int> Foo()
{
}

The first has no return (hence the compiler message). Which makes sense - it doesn't have enough context to know what to do. Should it return null? An empty enumerable? It can't know - so it won't let you compile.

public static IEnumerable<int> Foo()
{
    if(false)
    {
        yield return 0;
    }
}

The second does have a yield return (even if unreachable), which gives it enough context to know that you want to return an enumerable (so it can set up the necessary state machine). Now, when the code executes you never actually hit that yield return line (hence the compiler warning) - so what the caller will get is an empty enumerable. This is expected -

If you don't have a yield break, the compiler would assume one at the end of the function (just like a return; statement in a normal function)

Given how ugly and un-intuitive the second code sample is, you may wish to instead use:

public static IEnumerable<int> Foo()
{
    yield break;
}

Since it compiles, is clearer in its intent, and the compiler won't complain about unreachable code.

mjwills
  • 23,389
  • 6
  • 40
  • 63
  • In my real code, the condition tested a variable. I looked at what I'd just written and wondered why I wasn't getting a compiler error. Interesting gotcha. – StackOverthrow Jul 20 '19 at 00:09