明确无限循环在.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; 
      } 
     } 
    } 

我认为整个内部循环将被优化掉,除暴安良所有有效的回报。在字节码/编译器级别实际发生了什么,这一切都有意义吗?

+1

我觉得最后一个例子是编译器的说法的情况下,*“我希望他们知道他们在做什么.....“* – ChaosPandion

+0

+1从未想过这些情况。 – Arun

由于该方法的结尾是无法访问,编译器不会标记此。这不是一个问题 - 只有在不返回值的情况下才能结束方法(右大括号),这只是一个问题。

这不是编译器优化一个事 - 这是继定义为可达在规范中规定的情况。

注意,你并不需要一个return语句在所有...这个代码是没有用的,但非常有效:

public int EndlessLoop() 
{ 
    while (true) 
    { 
    } 
} 
+1

+1为了让光线“可达性”! – Arun

+2

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. 
}