2012-03-01 41 views
3

顯然標題是tongue in cheek,但我已經檢查並進行了雙重檢查,並且在邏輯中看不到錯誤。使用未初始化的變量 - 編譯器中斷

編譯器抱怨變量parsed可能未在return語句中初始化。我不同意。我們哪一個是錯的,爲什麼?

public DateTime? Test(string nextDate) 
{ 
    DateTime parsed; 

    if (nextDate != "TBC" && !DateTime.TryParse(nextDate, out parsed)) 
    { 
     throw new Exception(); 
    } 

    if (nextDate == "TBC") 
     return null; 

    return parsed; 
} 
+0

幽默是主觀的。如果你堅持手頭的問題,你可能會得到更好的迴應。 – adelphus 2012-03-01 10:14:09

+0

@adelphus感謝您的建議,但我認爲標題很好地描述了這個問題。這不應該是一個笑話。如果以某種方式冒犯了你,歡迎編輯它。無論如何,我已經得到了我的答案。 – fearofawhackplanet 2012-03-01 10:28:01

+0

那麼,這不應該是一個笑話?那麼你實際上認爲你的代碼有問題意味着編譯器壞了?就我個人而言,我並不在乎,但是對於許多人來說,假設編譯器(或操作系統或API或......)存在自己的代碼問題是一個貧窮的開發人員的標誌。 – adelphus 2012-03-01 11:17:11

回答

6

不,編譯器根本沒有損壞。

編譯器並不意味着能夠告訴

if (nextDate != "TBC") 

if (nextDate == "TBC") 

是互斥的。它沒有試圖在兩個條件之間建立任何聯繫。所以它不能說你會肯定已經撥打DateTime.TryParse(nextDate, out parsed),如果你得到儘可能return parsed;

基本上,編譯器遵循相對簡單的規則來確定明確的分配(和可達性)。簡單的規則很容易推理,易於實現,並易於編碼。

幸運的是,你可以讓你的代碼更簡單使其編譯在同一時間:

public DateTime? Test(string nextDate) 
{ 
    if (nextDate == "TBC") 
    { 
     return null; 
    } 

    DateTime parsed;  
    if (!DateTime.TryParse(nextDate, out parsed)) 
    { 
     throw new Exception(); 
    } 
    return parsed; 
} 

現在,我們在一個地方處理「TBD」的「特殊情況」然後我們可以忽略其餘代碼的特殊情況,並無條件地致電TryParse,並保留parsed的明確分配。

1

因爲out是if語句的一部分,所以您必須需要初始化該值。

因爲如果從左到右,在你的情況下nextDate != "TBC"首先得到驗證,並比下一個語句得到檢查。

所以這就像

if(fist check) 
{ 
if(second check) 
{ 
} 
} 
3

如果nextData == "TBC",你TryParse沒有被調用,因爲整個狀態不是真的呢。因此parsed可能未被初始化。

+2

我懷疑OP的觀點是,如果'nextData ==「TBC」'那麼我們將不需要'parsed'的值(因爲我們之前返回) - 但編譯器不必考慮這個。 – 2012-03-01 10:02:12

+0

你說得對。我怕我錯過了一點... – 2012-03-01 10:08:02

3

你們都是對的。

未初始化變量檢查的邏輯查看所有可能的控制流路徑,而無需進行更深入的邏輯分析。編譯器的這一部分不關心nextDate == "TBC"nextDate != "TBC"從來都不是這樣。所以編譯器是正確的,從他的PoV。

您不想在編譯器中深入分析程序邏輯。你想要簡單易懂的規則。在複雜的情況下,編譯器需要基本上在編譯時運行所有可能的輸入值來確定變量是否已初始化。

而你是對的,因爲你知道條件會生效,所以如果它沒有被初始化,變量的使用永遠不會被達到。


我已經重寫你的函數是這樣的:

public DateTime? Test(string nextDate) 
{ 
    DateTime parsed; 

    if (nextDate == "TBC") 
     return null; 

    if(!DateTime.TryParse(nextDate, out parsed)) 
     throw new Exception(); 

    return parsed; 
} 

但是既然你反正拋出一個異常,你可能想使用Parse而不是TryParse