.NET 中是否明确将无限循环作为特殊情况进行处理?
今天早些时候,当我编写一个方法时,我突然意识到我不确定我正在实现的习惯用法到底为什么会编译。如果其他所有内容都被抽象掉,它看起来会像这样:
private int Example()
{
while (true)
{
if (some condition)
{
return 1;
}
}
}
您有一个显式的无限循环,以及循环内的一些条件,这些条件导致循环以 return 语句结束。让我们暂时忽略为什么我这样做,而不是检查 while 子句中的终止条件,因为答案很复杂且无关紧要——我想知道的是为什么编译器不使用“Not”来标记它所有路径都会返回一个值。”错误,严格来说,并非所有路径都会返回值。从未进入 while 循环的情况(当然,永远不会发生)不会返回任何内容。
现在,我可以想象它发生的原因有两个:这是由于其他原因而发生的优化的副作用,或者编译器明确处理这种情况以允许这种习惯用法。我的直觉是这可能是第一个案例。例如,我对此编译一点也不感到惊讶:
private int Example2()
{
if (true) return 1;
}
因为编译器在 if 中看到常量 true,并优化了条件。不过,我真的不明白为什么这会“修复”第一个例子。
哦,更奇怪的是,如果正在进行一些消除循环的优化,则可以编译:
private int Example3()
{
while (true)
{
if (false)
{
return 1;
}
}
}
我认为整个内部循环将被优化掉,消除所有有效的返回。在字节码/编译器级别实际上发生了什么,使得这一切都有意义?
Earlier today, as I was coding a method and it struck me that I wasn't sure exactly why the idiom I was implementing compiles. If everything else is abstracted away, it would look something like this:
private int Example()
{
while (true)
{
if (some condition)
{
return 1;
}
}
}
You have an explicitly infinite loop, and some set of conditions inside the loop that cause the loop to end with a return statement. Let's ignore for the time being why I was doing this as opposed to checking for a termination condition in the while clause as the answer is convoluted and irrelevant -- what I want to know is why the compiler doesn't flag this with a "Not all paths return a value." error, as, strictly speaking not all paths do return a value. The case in which the while loop is never entered (which, of course, never happens) doesn't return anything.
Now, there are two reasons I can imagine it happening: this is a side effect of optimization that's occurring for other reasons, or this case is explicitly being handled by the compiler to allow this idiom. My instinct is that it's probably the first case. It doesn't surprise me at all, for instance, that this compiles:
private int Example2()
{
if (true) return 1;
}
Because the compiler sees a constant true in the if, and optimizes the conditional away. I don't really get why this would "fix" the first example, though.
Oh, and even more weirdly, if some optimization that gets rid of the loop is in play, this compiles:
private int Example3()
{
while (true)
{
if (false)
{
return 1;
}
}
}
I would think that the entire inner loop would be optimized away, getting rid of all of the valid returns. What's actually going on here at the bytecode/compiler level that makes this all make sense?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
编译器不会标记这一点,因为该方法的结尾无法到达。这不是问题 - 只有当您可以到达方法的末尾(右大括号)而不返回值时,这才是问题。
这不是编译器优化的问题 - 这是遵循规范中规定的可达性定义的情况。
请注意,您根本不需要 return 语句...此代码无用,但完全有效:
The compiler doesn't flag this because the end of the method is unreachable. That's not a problem - it's only a problem if you can get to the end of the method (the closing brace) without returning a value.
This isn't a matter of compiler optimization - it's a case of following the definitions for reachability laid down in the spec.
Note that you don't need a return statement at all... this code is useless, but perfectly valid:
为了给您提供此类无限循环的用例,请考虑以下代码:
然后在其自己的线程上运行此方法,从而异步处理键盘输入(这是轮询模式,通常最好有一个事件系统) 。
您可能会想象线程在完成时会返回状态代码,因此该方法的返回值为 int。然而,由于这个特定的线程永远不会完成,所以该方法不包含任何 return 语句根本不是问题。 C# 设计者了解这些用例并使上述方法合法。
请注意,确定特定方法是否始终返回值的一般问题是不可判定的(即无法通过任何计算机程序解决)。因此,C# 编译器可能会抱怨总是返回值的代码(尽管它永远不会接受不返回值的程序):
To give you a use case for these kinds of infinite loops, consider the following code:
You then run this method on its own thread, thereby asynchronously handling keyboard input (this is the polling pattern, having an event system in place is usually preferable).
You might imagine threads to return status codes when they are finished, so the return value of the method is int. However, since this particular thread will never finish, it's not a problem at all that the method does not contain any return statement. The C# designers knew about these of use cases and made the above method legal.
Note that the general problem of figuring out whether a particular method will always return a value is undecidable (ie, cannot be solved by any computer program). Therefore, the C# compiler might complain about code that will always return a value (though it will never accept programs that do not):