2011-09-06 124 views
20

今天早些時候,當我編寫一個方法時,它讓我吃了一驚,我不確定爲什麼我正在執行編譯的習慣用法。如果一切被抽象化了,它會是這個樣子:明確無限循環在.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

回答

29

由於該方法的結尾是無法訪問,編譯器不會標記此。這不是一個問題 - 只有在不返回值的情況下才能結束方法(右大括號),這只是一個問題。

這不是編譯器優化一個事 - 這是繼定義爲可達在規範中規定的情況。

注意,你並不需要一個return語句在所有...這個代碼是沒有用的,但非常有效:

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

+1爲了讓光線「可達性」! – Arun

+2

Eric Lippert是編譯器開發人員之一,如果您好奇的話,他會在博客中介紹可訪問性:http://blogs.msdn.com/b/ericlippert/archive/tags/reachability/ –

3

爲了讓你爲這些類型的無限循環的使用情況下,考慮以下代碼:

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