为什么使用yield return的此代码进行编译?

No *_*o U 4 c# ienumerable

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

public static IEnumerable<int> Foo()
{
}
Run Code Online (Sandbox Code Playgroud)

并非所有代码路径都返回值

但是,此编译仅带有有关无法访问代码的警告:

public static IEnumerable<int> Foo()
{
    if(false)
    {
        yield return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

这产生一个空的可枚举。为什么这样做有效,并且它是定义的行为?

mjw*_*lls 7

public static IEnumerable<int> Foo()
{
}
Run Code Online (Sandbox Code Playgroud)

第一个没有返回(因此编译器消息)。这很有意义-它没有足够的上下文来知道该怎么做。它应该返回null吗?一个空的枚举?它不知道-因此它不会让您编译。

public static IEnumerable<int> Foo()
{
    if(false)
    {
        yield return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个确实有一个yield return(即使无法访问),它提供了足够的上下文来知道您返回一个可枚举的对象(因此它可以设置必要的状态机)。现在,当代码执行时,您实际上不会碰到这一yield return行(因此会发出编译器警告)-因此,调用者将得到的是一个空的可枚举值。这是预期的 -

如果没有屈服中断,则编译器将在函数末尾假定一个(就像return;普通函数中的语句一样)

鉴于第二个代码示例多么丑陋和不直观,您可能希望使用:

public static IEnumerable<int> Foo()
{
    yield break;
}
Run Code Online (Sandbox Code Playgroud)

由于它可以编译,因此其意图更加清楚,并且编译器将不会抱怨无法访问的代码。