[英]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 break
或yield 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.