【C# Skills】03 - Enums 列舉

列舉,是逐一舉出的意思
用來定義一個集合的各個項目
在C# 中的列舉,可以定義列舉的名稱及值,而值只能為以下幾種類別
byte, sbyte, short, ushort, int, uint, long, ulong
基本上常用int,比較直觀

以下舉例:
季節

// 預設的列舉型別為int
// 可以不寫繼承,也可以指定,以下為指定的寫法
// 預設值會照順序排列,以下範例中Spring = 0, Summer = 1 以此類推
public enum Season : int
{
    Spring, // 0
    Summer, // 1
    Autumn, // 2
    Winter  // 3
}

列舉的值可以預設,但有時候需要從中插入值,值的順序會亂掉可能會影響程式運行
例如資料庫寫3 以為是 Season.Winter,但是插入新定義後後 Season.Winter 變成4,程式讀出來可能會錯誤
為了解決這個問題,也可以指定值

public enum Season : int
{
    Spring = 0,
    Summer = 1,
    Autumn = 2,
    Winter = 3
}

另外提一個進階用法
如果想要一次代表兩個值,可以參考以下做法

// 加上Flag 屬性,利用位元做運算
// 為了運算後不要有重複的狀況,使用2的次方來定義列舉的值
[Flags]
public enum Season : int
{
    None = 0,
    Spring = 1,
    Summer = 2,
    Autumn = 4,
    Winter = 8
}

public class FlagsEnumExample
{
    public static void Main()
    {
    	// 以位元運算來思考
    	// 1 | 2 --二進位--> 001 | 010 --做OR--> 011 --十進位--> 3
    
        // 氣溫舒適的季節為春秋兩季
        Season goodSeasons = Season.Spring | Season.Autumn;	
        // 如果將goodSeasons 換成int
        int val = (int)goodSeasons;
        // 結果:val = 5 (1 + 4)
        
        // 想要比較現在的季節是不是舒適的季節
        Season inputSeason = Season.Winter;
        bool isGoodSeasons = (goodSeasons & inputSeason) == inputSeason;
        // 結果:isGoodSeasons = false
        
        // 反向操作:從數字轉換成列舉
        var season = (Season)12;
        // 結果:season = Season.Autumn | Season.Winter; // 4 + 8
    }
}

如有理解錯誤,歡迎指教

References:
https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/builtin-types/enum
https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/builtin-types/enum#enumeration-types-as-bit-flags