本篇算是整理,針對列舉 (enum) 型別的一些使用上的心得。

首先要先點出的是,列舉是 Value Type,不是 Reference Type,因此在列舉型別物件中,儲存的值不會是 null,所以如果錯誤使用它的話,有時候會產生意想不到的結果。

第二點是,從前一篇 [C#][筆記] default 關鍵字針對不同型別的回傳值整理 文章的實驗結果中,我們可以看到,針對列舉型別,使用 default 關鍵字,回傳的值是 0。

我們舉下面的 Sample Code 做為範例 (這是真實案例,我從別人的 code 中抽出來的),程式中我們定義了一個列舉 TestEnum,有 Value1、Value2、Value3 三個成員。

/// 
/// 測試用列舉
/// 
public enum TestEnum
{
    Value1,
    Value2,
    Value3
}

在主程式中,我們有一個 List 變數,名稱為 testList,內含有列舉中的 Value1 與 Value2 成員。程式的需求,是判斷這個 List 變數中,有沒有包含 Value3 這個列舉值成員。

因為有人把列舉視為 Reference Type,因此就寫出了以下的程式碼︰

bool isListContainValue3 = false;
List<TestEnum> testList = new List<TestEnum>() { TestEnum.Value1, TestEnum.Value2 };
isListContainValue3 = testList.FirstOrDefault(element => element == TestEnum.Value3) != null;

// 總是印出 True
Console.WriteLine(isListContainValue3);

我們先不管誤用 FirstOrDefault() 這個 method 來做「判斷一個 List 是否包含某個值」的問題,上述的程式,如果我們真正執行的話,我們會發現,程式永遠會印出 True,即使上述 testList 並不包含 Value3 這個列舉成員。

會出現這問題,是因為錯誤將列舉視為 Reference Type,認為如果在清單中查不到成員的話,default(TestEnum) 會回傳 null 值。

但我們已經知道,列舉其實是 Value Type,因此列舉變數是不能儲存 null 值的。在此例中,testList.FirstOrDefault() 這個 method 會回傳的是 default(TestEnum),也就是 TestEnum.Value1 這個列舉成員。也因此結果永遠不會是 null,印出來的值則永遠印出的是 True。

算是以一個例子,來說明誤解列舉型別,在某些情形下,是真的會造成問題的。

最後,以上述的需求來看,其實可以直接使用 List 類別的 Contains method,就可以了︰

isListContainValue3 = testList.Contains(TestEnum.Value3);


References: