2008-12-06 26 views
8

如果枚舉應該有未初始化的值,我們正在進行辯論。例如。我們有應該枚舉具有未初始化的值。

public enum TimeOfDayType 
{ 
    Morning 
    Afternoon 
    Evening 
} 

public enum TimeOfDayType 
{ 
    None 
    Morning 
    Afternoon 
    Evening 
} 

我認爲,不應該有任何沒有但你必須默認爲在初始化一些有效的價值。但是其他人認爲應該通過另一個是None或NotSet的枚舉來指示uniitized狀態。

想法?

回答

13

說到可空類型 - 我認爲它們可以用來解決強制/不強制枚舉初始化的問題。假設我們有

enum Color { Red, Blue } 

而且假設你有一個函數:

void Draw(Color c); 

這個函數說,它需要有效Color。然而,我們也可以有這樣的功能:

void Draw(Color? c); 

,指出該函數可以處理不被通過的顏色(null將被傳遞給表示「不關心」)。

嗯,它是None成員的替代方案之一。

+0

同意,最乾淨的解決方案是可空類型。它也很好地映射到DB模式。 – 2008-12-06 02:52:17

+9

不幸的是,.NET中的枚舉不會強制您傳遞有效的值。我可以通過(Color)123123編譯並運行得很好--Draw方法將需要進行驗證:( – 2008-12-06 08:11:01

+2

可能是C的繼承,編譯器不知道枚舉是否被用作真正的枚舉類型,或者作爲一組標誌,因此它將手放在空中投降 – 2008-12-06 13:31:17

1

取決於如何使用類型。這種類型的用戶通常不會有一個「未定義」值,因爲您不必特殊處理一個值。但是如果你需要一個(因爲值有時需要處於一個不是枚舉值的狀態),那麼你需要一個。您通常不會使用兩個枚舉而不是一個保存任何特殊情況代碼。

這有點像問你是否應該使用可爲空的類型。

3

只要添加到弗蘭克的答案,我會選擇一個枚舉中的「無」項的可能性之一是當枚舉被用作標誌。 'None'項目的ID爲0.

4

可以使用一個可爲空的枚舉作爲以前答案中的一個解決方案。但是可枚舉枚舉的缺點是,它使得客戶端在每次使用枚舉時檢查一個空值。相反,如果您的默認值爲「無」,您可以選擇使用開關作爲有意義的值,並忽略「無」,而不必擔心枚舉變量可能爲空。

無論如何,我認爲有一個默認值「無」或使枚舉爲空是有意義的,只有當枚舉被用作某個類的默認構造函數中的參數。而且你必須問自己 - 該類別的對象不應該有一些有意義的默認值嗎?將您的示例與TimeOfDayType枚舉結合使用 - 如果使用TimeOfDayType.None初始化對象,則在將值更改爲Morning,Afternoon或Evening之前,無法使用它。所以你不能說默認是Morning而不是None嗎?或者 - 哪一個更好 - 在你已經知道他們需要哪個枚舉值之後,你不能創建你的對象嗎?我認爲如果在早期設計階段正確解決了這個問題,那麼根本就不需要爲你的枚舉設置一個特殊的默認值。

當然,以上全部是泛化。也許它不適用於你的特定場景,所以如果你提供一些細節,我們可以更徹底地討論這個問題。

4

在「默認」成員的abscence,我認爲這是有價值的有代表一種價值的文字INT 0

不管如何,一個給定的枚舉將與文字值0創建最直接向前的情況下,這是作爲一個結構的成員。 C#結構將始終有一個空的默認構造函數,它將所有字段初始化爲默認值。在枚舉的情況下,這將是字面值0.問題是如何處理它。

對我來說,這是一個風格問題:如果enum沒有明確地初始化爲一個值,應該給它一個任意的有效值還是一個指明缺少顯式初始化的特定值?

enum Color { Unknown, Red, Blue } 
enum Color2 { Red,Blue } 
struct Example<T> { 
    Color color; 
} 

static void SomeMethod() { 
    var v1 = new Example<Color>(); 
    var v2 = new Example<Color2>(); 
} 

在v1的情況下,如果檢查色域,它將顯式標記爲未初始化的域。在第2版中,該字段很簡單,就是「紅色」。程序員無法檢測到顯式設置爲「紅色」或隱式默認值爲「紅色」。

這導致問題的另一種情況是針對枚舉值執行switch語句。讓我們稍微改變Color2的定義。

enum Color2 { Red = 1, Blue = 2 } 
static void SomeOtherMethod(p1 as Example<Color2>) { 
    switch (p1.color) { 
    case Color.Red: {} 
    case Color.Blue: {} 
    default: {throw new Exception("What happened?"); } 
    } 
} 

該開關處理枚舉中的每個顯式值。然而,這個代碼將失敗,例如<Color2>的默認構造函數,並且無法抑制此構造函數。

這帶來了一個性能稍微更重要的規則:有文字值0

7

我總是設置我的枚舉文字之一爲零明確的枚舉值。該文字不一定總是被命名爲「無」或「未設置」。這取決於是否存在一個默認行爲很好的文字。

我將1設置爲零,因爲枚舉(除了可爲空的枚舉)總是由CLR在內存中初始化爲零。如果你沒有定義一個文字,這個記憶包含非法值。同樣當你使用枚舉作爲標誌。默認值不能用於按位對齊。結果將始終爲零。

當您啓用FxCop時,它會檢查您是否將文字定義爲默認值。當他們有這個規則時似乎是一種「良好的做法」。