为什么使用 yield return 的代码可以编译?

Why does this code using yield return compile?

如您所料,此代码会产生编译器错误:

public static IEnumerable<int> Foo()
{
}

not all code paths return a value

然而,这只编译了关于不可访问代码的警告:

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

这会生成一个空的可枚举对象。为什么这行得通,它是否定义了行为?

public static IEnumerable<int> Foo()
{
}

第一个没有 return(因此是编译器消息)。这是有道理的——它没有足够的上下文来知道该做什么。 应该returnnull吗?一个空的枚举?它不知道 - 所以它不会让你编译。

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

第二个确实有一个 yield return(即使无法访问),这给了它足够的上下文来知道你想要到return一个可枚举的(所以它可以设置必要的状态机)。现在,当代码执行时,您实际上并没有点击 yield return 行(因此出现编译器警告)——因此调用者将得到一个空的可枚举对象。 这是 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)

考虑到第二个代码示例有多丑 un-intuitive,您可能希望改用:

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

自编译以来,其意图更加清晰,编译器不会抱怨无法访问的代码。