Are explicitly Infinite Loops handled in .NET as a special case?
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 开发者_StackOverflow中文版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?
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:
public int EndlessLoop()
{
while (true)
{
}
}
To give you a use case for these kinds of infinite loops, consider the following code:
public int KeyboardChecker()
{
while (true)
{
if (KeyHasBeenPressed())
{
HandleKeyPress();
}
}
}
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):
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.
}
精彩评论