明确无限循环在.NET中处理为特殊情况?
今天早些时候,当我编写一个方法时,它让我吃了一惊,我不确定为什么我正在执行编译的习惯用法。如果一切被抽象化了,它会是这个样子:明确无限循环在.NET中处理为特殊情况?
private int Example()
{
while (true)
{
if (some condition)
{
return 1;
}
}
}
你有一个明确的无限循环,有的一套导致循环用一个return语句结束循环内的条件。让我们暂时忽略为什么我这样做,而不是在while子句中检查终止条件,因为答案是复杂而且不相关的 - 我想知道的是为什么编译器不会用“Not所有路径都会返回一个值。“错误,严格地说,并非所有的路径都会返回一个值。 while循环从不输入(当然,这从来不会发生)的情况不会返回任何内容。
现在,我可以想象它发生了两个原因:这是由于其他原因发生的优化的副作用,或者编译器明确地处理此情况以允许此成语。我的直觉是,这可能是第一种情况。这并不让我感到吃惊可言,比如,这个编译:
private int Example2()
{
if (true) return 1;
}
因为编译器看到一个真正不变的,如果和条件远优化。但我不明白为什么这会“修复”第一个例子。
哦,更古怪,如果一些优化是摆脱循环是在玩,这编译:
private int Example3()
{
while (true)
{
if (false)
{
return 1;
}
}
}
我认为整个内部循环将被优化掉,除暴安良所有有效的回报。在字节码/编译器级别实际发生了什么,这一切都有意义吗?
由于该方法的结尾是无法访问,编译器不会标记此。这不是一个问题 - 只有在不返回值的情况下才能结束方法(右大括号),这只是一个问题。
这不是编译器优化一个事 - 这是继定义为可达在规范中规定的情况。
注意,你并不需要一个return语句在所有...这个代码是没有用的,但非常有效:
public int EndlessLoop()
{
while (true)
{
}
}
+1为了让光线“可达性”! – Arun
Eric Lippert是编译器开发人员之一,如果您好奇的话,他会在博客中介绍可访问性:http://blogs.msdn.com/b/ericlippert/archive/tags/reachability/ –
为了让你为这些类型的无限循环的使用情况下,考虑以下代码:
public int KeyboardChecker()
{
while (true)
{
if (KeyHasBeenPressed())
{
HandleKeyPress();
}
}
}
您然后在其自己的线程中运行该方法,从而异步处理键盘输入(这是轮询模式中,代替具有事件系统通常优选)。
您可能会想到线程在完成时返回状态码,因此该方法的返回值为int。然而,由于这个特定的线程永远不会完成,所以该方法不包含任何return语句并不是问题。 C#设计人员知道这些用例,并使上述方法合法。
请注意,确定某个特定方法是否总能返回值的一般问题是不可判定的(即,不能由任何计算机程序解决)。因此,C#编译器可能会抱怨的代码,将始终返回一个值(尽管它永远不会接受没有程序):
public int DoWork()
{
// The compiler doesn't figure out this will always be true.
if (((int)Math.Sqrt(4)) == 2)
{
return 3;
}
// And therefore complains that not all code paths return a value for this method.
}
我觉得最后一个例子是编译器的说法的情况下,*“我希望他们知道他们在做什么.....“* – ChaosPandion
+1从未想过这些情况。 – Arun