2010-02-22 73 views
13

這只是一個「我很好奇」的問題。C# - 如何創建一個不可檢測的無限循環?

在C#-in深入喬恩斯基特說,大約lambda表達式:
「如果有一個非空返回類型每個代碼路徑必須返回一個值兼容」(頁233)

的腳註接着說:
「的代碼路徑拋出異常並不需要返回過程中的價值,也不做檢測的無限循環。」(第233頁)

我想知道什麼構成了無法察覺的無限循環?

這隻能通過邏輯來完成嗎?還是通過使用外部因素(如數據庫或文件系統)來完成?

+0

@JonSkeet也許他可以澄清。 – 2010-02-22 18:50:29

回答

21

什麼喬恩指的是在本說明書中的第8.1節中描述。編譯器只能檢測到非常簡單的無限循環,如:

while(true) { if (0 != 0) return 123; } 

編譯器是足夠聰明地看到,回報率從未達到的,因此該循環將永遠運行下去。它是合法的,但瘋了,說:

int M() { while(true) { } } 

,因爲雖然沒有路徑返回一個int,也沒有路徑返回沒有返回一個int!

編譯器不夠聰明,找不到其他種類的無限循環。例如:

int x = 123; 
while(true) { if (x * 0 != 0) break; } 

這顯然是一個無限循環。但編譯器不知道這一點。編譯器說:「好吧,也許有一些x的值,其中x * 0不是零,因此中斷可以到達,所以這不是一個無限循環。你和我知道這是不可能的,因爲我們知道數學,但編譯器沒有。

如果您想了解詳情,請閱讀第8.1節。

+3

我其實不記得寫這個 - 這表明腳註是由於你的影響:) – 2010-02-22 23:04:55

+2

@Jon:你最初寫道「拋出異常的代碼路徑不需要返回值,當然」。我注意到可檢測的無限循環也被視爲無法達到的終點。 – 2010-02-22 23:36:06

+2

對 - 這似乎是我們每個人都想出來的更可能的細節水平:) – 2010-02-23 00:09:26

3

使用外部資源創建無限循環,甚至濫用接口等工具都非常簡單。

例如:

public interface INumbers 
    { 
     int GetNumber(int arg); 
    } 
    public class StaticNumber : INumbers 
    { 
     public int GetNumber(int arg) 
     { 
      return 1; 
     } 
    } 
    public void DoStuff(INumbers num) 
    { 
     int i = 42; 
     while ((i = num.GetNumber(i)) != 0) 
     { 
      ; 
     } 
    } 

然後簡單

Action action =() => DoStuff(new StaticNumber());