[英]Why does the compiler complain that 'not all code paths return a value' when I can clearly see that they do?
我試圖找出編譯器為什么有這個功能的問題。 它給了我“並非所有的代碼路徑返回一個值”的錯誤,但我看不到的情況下控制流將傳遞到if( a )
的表達沒有a
是真正的(所以if( a )
是多余的,但編譯器似乎沒有認識到這一點)。
public static Boolean Foo(Boolean x)
{
Boolean a = false;
if( x )
{
a = true;
}
else
{
try
{
SomethingThatMightThrow();
Assert.IsFalse( a );
return a;
}
catch(Exception)
{
a = true;
}
}
if( a )
{
return x;
}
}
立即修復是簡單地完全刪除if( a )
guard語句並立即return x
- 但是為什么編譯器會抱怨,即使它應該能夠靜態地證明所有可能的代碼路徑都會return
一個return
語句? 至關重要的是,沒有循環,這通常是它無法證明return
主要原因。
我正在使用VS2015 Update 3。
有一個支持的方案是a
是false
,當你達到你的函數的末尾。 這情形是,當你調試代碼,並使用調試器可以設置 a
以false
。
C#編譯器規則設計簡單。 在C#借用的語言中,函數可能無法返回任何內容的問題是編譯器警告無法解決的問題。 有太多的誤報,因此警告被調整為僅警告明顯的案例,引入假陰性。 C#的規則是一種妥協,如果對於熟悉規則的人來說,誤報是可以接受的,並且假陰性是不可接受的。 您可以保證,如果您的函數具有不返回值的代碼路徑,編譯器會檢測到它。
這些簡單規則的一部分是不考慮變量的值。 即使靜態保證a
是true
,編譯器也不能利用這個事實。
@PetSerAl已經引用了C#語言規范中的相關措辭:
8.1終點和可達性
[...]
要確定特定語句或端點是否可訪問,編譯器將根據為每個語句定義的可訪問性規則執行流分析。 流分析考慮了控制語句行為的常量表達式(第7.19節)的值,但不考慮非常量表達式的可能值。 換句話說,出於控制流分析的目的,給定類型的非常量表達式被認為具有該類型的任何可能值。
這是最新發布的語言規范的一部分,即C#5.0。 您正在使用的版本,C#6.0(VS2015提供的版本),還沒有已發布的規范,因此措辭可能略有不同,但正如您的編譯器所示,實際上相同的規則仍然適用。
它是運行時與編譯時
你的例子太復雜了。 這也不會編譯:
static int Test()
{
bool f = true;
if (f)
{
return 1;
}
else
{
//Not all code paths return a value
}
}
另一方面,這將:
static int Test()
{
if (true)
{
return 1;
}
else
{
//No error
}
}
我猜測無論有什么驗證機制都沒有足夠的邏輯來推斷運行時變量的內容。 編譯時變量沒問題。
我認為編譯器對代碼進行了非常簡單的分析,因此必須明確給出返回。
這看起來可能是錯誤的決定,但在處理復雜代碼時,返回的值可能不明確。 所以,程序員被迫返回它。
您的示例可以減少到最小,如下所示:
public static Int32 Main(String[] args)
{
var printUsage = true;
if (printUsage)
{
return 0;
}
// return nothing, so compiler is not happy
}
雖然仍然得到錯誤。
注意:如果您使用Resharper,它將執行您想要的分析並相應地發出警告:
if (printUsage) // Warning: expression is always true
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.