繁体   English   中英

收益率返回和“并非所有代码路径返回值”

[英]Yield return and “not all code paths return value”

为什么以下代码:

private static IEnumerable<int> TestYield(bool check)
{
    if (check)
    {
        return 1;
    }
    else
    {
        Console.WriteLine("In the else");
    }
}

产生错误,“并非所有代码路径都返回值”。 但是,以下代码不会产生相同的错误:

private static IEnumerable<int> TestYield(bool check)
{
    if (check)
    {
        yield return 1;
    }
    else
    {
        Console.WriteLine("In the else");
    }
}

唯一的区别是产量。 产生不同的产量不会导致同样的错误?

包含yield breakyield return语句的任何方法体都是迭代器块 在迭代器块中,执行到达方法的右括号是可以接受的,因为它只相当于yield break - 它是序列的结束。

在具有非void返回类型的常规方法中,语句的右括号可以访问是错误的。 (另外, return 1;不是常规方法中的有效语句,返回类型为IEnumerable<int> 。)

当你使用return时,因为你的else语句没有返回任何东西,它会给你提到的错误,因为你返回int类型它也会给出错误“无法转换表达式类型int返回类型IEnumerable”。

当您使用yield return时,yield关键字会创建一个状态机来维护状态信息。 根据MSDN :“当迭代器方法中达到yield return语句时,返回表达式,并保留代码中的当前位置。下次调用迭代器函数时,将从该位置重新执行。”

现在,对于你的问题“在其他方面会发生什么”,我看了一下用ILSpy生成的IL代码。 我创建了一个名为YTest的类,并添加了以yield返回的方法。 这是生成的代码:

internal class YTest
{
    [IteratorStateMachine(typeof(YTest.<TestYield>d__0))]
    public static IEnumerable<int> TestYield(bool check)
    {
        int num;
        while (num == 0)
        {
            if (!check)
            {
                Console.WriteLine("In the else");
                IL_52:
                yield break;
            }
            yield return 1;
        }
        if (num != 1)
        {
            yield break;
        }
        goto IL_52;
    }
}

编译器在引擎盖下添加yield break语句。

使用yield关键字时,你应该牢记这些要点(除了msdn,引用自https://www.infoworld.com/article/3122592/application-development/my-two-cents-on-the-yield-关键字在-c.html

):

  • 你不能在try-catch块中有yield return语句,尽管你可以在try-finally块中使用它

  • 你不能在finally块中包含yield break语句

  • 使用yield的方法的返回类型应该是IEnumerable,IEnumerable,IEnumerator或IEnumerator

  • 您的方法中不能使用ref或out参数,其中使用了yield

  • 您不能在匿名方法中使用“yield return”或“yield break”语句

  • 您不能在“不安全”方法中使用“yield return”或“yield break”语句,即标记为
    “unsafe”关键字表示不安全的上下文

在第一个代码中,您只返回1,这是一个整数值,但方法的返回类型是

IEnumerable<int>

按照微软; 他们明确表示你应该使用

 yield return statement to return each element one at a time. 

您可以使用foreach语句或LINQ查询来使用迭代器方法。 所以基本上,如果你不想迭代那么就不需要使用yield和IEnumerable但是如果你真的想要遍历你的数据或文件那么你应该使用yield

有关更多信息,请阅读MS的Yield

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM