2012-04-11 123 views
2

爲什麼在下面的代碼中,.NET編譯器無法確定所有代碼路徑都返回值?.NET編譯器和「並非所有代碼路徑都返回值」

bool Test(bool param) { 
    bool test = true; 
    if (param) 
     test = false; 
    else 
     test = false; 
    if (!test) 
     return false; 
} 

錯誤CS0161:並非所有的代碼路徑都返回一個值!

該代碼可以重構 - 但編譯器不提示。然而,所有的返回路徑都被覆蓋 - 那爲什麼編譯器會抱怨他們不是?

編輯:我在這裏想得出的結論是:

(error CS0161) + (all code paths obviously return a value) => refactor code. 

一旦你得到的是翻譯的習慣,我想一切正常。

+0

我想開發者並不覺得需要像這樣的代碼。 – 2012-04-11 21:31:02

+9

是否有您看到此編譯器錯誤的*有用*代碼的實際代碼片段? – 2012-04-11 21:31:14

+0

是的,您可以在上面添加幾行代碼,使其成爲非trival /真正有用的,但具有所有代碼路徑返回但編譯器仍然抱怨的所有特性。 – Ricibob 2012-04-11 21:33:21

回答

10

從C#語言規範4.0包含在Visual Studio 2010中

10.6.10「法體」:

當一個方法的返回類型不是void,每個返回的聲明該方法的主體必須指定一個可以隱式轉換爲返回類型的表達式。一定不能訪問返回值方法 的方法體的端點。換言之,在 值返回方法中,不允許控制流出方法主體的末尾 。

可達的定義是在這裏(強調):

8.1「結束點和可到達」:

如果語句都不可能通過執行來達到,語句據說可以到達 。相反,如果不可能執行語句,則說該語句不可達。

...

要確定某個特定語句或終點是否可到達,編譯器將根據爲每個語句定義的可達性規則執行流分析。流程分析考慮了控制語句行爲 的常量表達式(§7.19)的值,但非常量表達式 的可能值不被視爲

由於!test不是一個常量表達式(即使它會始終評估爲true),編譯有義務不考慮它的流動分析。這種限制的一個原因(也許是唯一原因)是在一般情況下進行這種流量分析是不可能的。

要消除錯誤,您需要在else子句中或無條件地在該方法結尾處有另一個return語句。

+0

+1找到規範參考 – phoog 2012-04-11 21:52:30

+0

嗯,我想這個拼出來。我只是驚訝地發現,非常量表達式的深度分析是零。我可以理解,分析可能會很快變得複雜,但它奇怪的編譯器會通過一些淺薄/微不足道的情況。 – Ricibob 2012-04-11 22:04:16

+8

@Ricibob:我們製作可達性分析儀的準確性越高,說明書就越難清楚地描述它,因此您越難了解您的程序是否正確。今天指定的語言試圖居住在算法可以理解的「最佳位置」,它捕獲了大多數可達性錯誤。在優先級列表中,將「錯誤肯定」錯誤的數量最小化不是很高。此外:錯誤指出你有機會改進代碼;對此感到高興! – 2012-04-11 22:12:19

3

這只是代表編譯器在初始化和執行哪些代碼方面的智能限制。

我偶爾遇到這個問題。但很少有這個問題。我通常只是重構一些代碼。

10

Eric Lippert's blog

的可達性分析是不是很聰明。它沒有意識到只有兩種可能的控制流程,並且我們已經用回報覆蓋了所有這些流程。

(博客文章是對switch聲明,但我估計可達性分析是不是更聰明的if語句。)

1

讓落後的分析代碼:

問題:代碼不會返回任何值。

問題:在代碼中返回值的位置?

答案:就在最後一行。

結論:因此,這行代碼(最後一行)應該總是返回一個值。

問題:最後一行總是返回一個值嗎?

答:沒有,只有testfalse,而它在第一行設置爲true返回值。

結論:正如編譯器所說,這個函數從不返回值,而它應該返回bool

相關問題