2014-08-30 97 views
3

我有以下枚舉:編譯抱怨未賦值的變量開關後枚舉

use of unassigned local variable 'str'

的代碼:

enum Foo { Bar, Baz }; 

在下面的代碼,編譯器與錯誤中止

string str; 
Foo foo = Foo.Bar; 

switch (foo) 
{ 
    case Foo.Bar: str = "a"; break; 
    case Foo.Baz: str = "b"; break; 
} 

str.ToLower(); 

switch涵蓋了所有可能的枚舉值。但編譯器仍然認爲str可能未被分配。這是爲什麼?當然,我可以在那裏放一個default的情況,但那是錯誤的,因爲錯誤在編譯時沒有被捕獲。例如,如果Foo枚舉稍後被修改並添加了新的值,那麼然後這將很好地得到編譯器錯誤。如果我使用default大小寫,那麼重新編譯時不會捕獲錯誤。

我想有沒有辦法讓編譯器接受switch沒有default情況如果Foo擴展以後產生一個錯誤?

回答

2

I suppose there is no way to get the compiler to accept a switch without a default case and raise an error if Foo is extended later on?

這是正確的。長話短說,編譯器這樣做的原因是,可以通過類型化一個int來指定foo一個不是有效enum Foo s值的值,從而可以繞過所有switch的情況。

,我在這樣的情況下使用的解決方案是增加一個斷言:

switch (foo) 
{ 
    case Foo.Bar: str = "a"; break; 
    case Foo.Baz: str = "b"; break; 
    default: Debug.Assert(false, "An enum value is not covered by switch: "+foo); 
} 
+0

斷言在這種情況下看起來是最好的主意。 – 2014-08-30 13:46:25

+0

您可以使用'Debug.Fail(...)'而不是'Debug.Assert(false,...)'。最後一個開關部分如何繼續?你會爲'str'和'break'分配一個虛擬值(如'null')嗎?或者你會拋出?你不能「跌倒」;交換機部分的端點必須無法訪問。 – 2015-06-09 22:04:12

1

枚舉是靜態類型和類型檢查。但是這種檢查並沒有擴展,以確保枚舉值只能假定定義的值。實際上,對於Flags枚舉變量通常不會假定任何單個定義的值。

就像是:

Foo f = (Foo)1234; //valid 

這就是爲什麼switch可以在運行時挑選default情況和str可能最終未初始化狀態使用。

某些語言比.NET枚舉(如Haskell和F#)具有更強的構造。

0

你最好的選擇是在你的第一行用空字符串初始化str。編譯器不能(或不會)試圖深入分析開關邏輯。

1

枚舉本質上是一個int和任何int值可以被分配給它。這通常沒有這將是根據良好做法發生,但就是爲什麼你需要處理默認情況下,或簡單地聲明瞭默認值(如空)字符串

1

Of course I could put a default case in there, but that would be wrong

。您的枚舉仍然可以包含其他數值,因爲C#中的枚舉只是編譯時間層的基礎數字表示之上 - 請考慮const字段。 Foo f = (Foo)int.MaxValue;仍然會編譯並運行,但現在你沒有它的開關箱。

根據您的界面,您可以將默認情況設置爲例外,使用空值或空字符串定義str