列舉型別(C# 參考)

列舉型別(或enum型別)是一種由基礎整數型別的一組具名常數所定義的值型別。 若要定義列舉型別,請使用 enum 關鍵詞並指定 列舉成員的名稱:

enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

預設情況下,列舉成員的相關常數值為型別 int。 它們從零開始,依照定義文字順序增加一。 您可以明確地將任何其他 整數數值 類型指定為列舉型別的基礎類型。 您也可以明確指定相關聯的常數值,如下列範例所示:

enum ErrorCode : ushort
{
    None = 0,
    Unknown = 1,
    ConnectionLost = 100,
    OutlierReading = 200
}

你無法在列舉型別的定義中定義方法。 若要為列舉型別新增功能,請建立 擴充成員

列舉型別 E 的預設值是由表達式 (E)0 所產生的值,即便零沒有對應的列舉成員。

從零隱含轉換

C# 允許從常值 0 隱含轉換成任何列舉類型,以及從 const 等於零的值進行隱含轉換。 當列舉不包含值為零的成員時,此行為可能會導致非預期的結果:

public enum GpioPort
{
    GpioA = 1,
    GpioB,
    GpioC,
    GpioD
}

public class ZeroConversionExample
{
    public static void Main()
    {
        // This compiles without warning but creates an invalid enum value
        GpioPort port1 = (GpioPort)0;
        Console.WriteLine($"port1: {port1}"); // Output: port1: 0

        // This also compiles due to implicit conversion from zero
        GpioPort port2 = GetPort(0);
        Console.WriteLine($"port2: {port2}"); // Output: port2: 0

        // Check if the enum value is valid
        bool isValid1 = Enum.IsDefined(typeof(GpioPort), port1);
        bool isValid2 = Enum.IsDefined(typeof(GpioPort), port2);
        Console.WriteLine($"port1 is valid: {isValid1}"); // Output: port1 is valid: False
        Console.WriteLine($"port2 is valid: {isValid2}"); // Output: port2 is valid: False

        // Safer approach - validate enum values
        if (Enum.IsDefined(typeof(GpioPort), 0))
        {
            GpioPort safePort = (GpioPort)0;
        }
        else
        {
            Console.WriteLine("Value 0 is not a valid GpioPort");
            // Handle the invalid case appropriately
        }
    }

    public static GpioPort GetPort(GpioPort port)
    {
        return port;
    }
}

在上述範例中,和 port1 都會port2指派 值0,但沒有GpioPort具有該值的成員。 Enum.IsDefined方法會確認這些列舉值無效。

這種隱含轉換存在,是因為 0 位元模式是所有結構型態的預設值,包括所有枚舉型別。 不過,它可以在您的程式代碼中引入 Bug。 為了避免這些問題:

  • 幾乎總是要在你的列舉中定義有價值 0 的成員。
  • 從數值類型轉換時,使用 Enum.IsDefined 來驗證列舉值。
  • 使用可能隱含轉換成列舉類型的數值參數時,請小心謹慎。

使用列舉型別來表示一組互斥值中的選擇,或是多個選項的組合。 若要表示選擇的組合,請將列舉型別定義為位旗標。

列舉型別作為位元標誌

如果你想讓列舉類型代表多個選擇的組合,請為這些選擇定義枚舉成員,使得每個選擇都是一個位元欄位。 也就是說,將這些枚舉成員的相關值視為二的冪次方。 接著,使用 位元邏輯運算子 |& 分別組合選項或交集選項組合。 若要指出列舉類型宣告位元欄,請將 Flags 屬性套用至它。 如下列範例所示,您也可以在列舉型別的定義中包含一些典型的組合。

[Flags]
public enum Days
{
    None      = 0b_0000_0000,  // 0
    Monday    = 0b_0000_0001,  // 1
    Tuesday   = 0b_0000_0010,  // 2
    Wednesday = 0b_0000_0100,  // 4
    Thursday  = 0b_0000_1000,  // 8
    Friday    = 0b_0001_0000,  // 16
    Saturday  = 0b_0010_0000,  // 32
    Sunday    = 0b_0100_0000,  // 64
    Weekend   = Saturday | Sunday
}

public class FlagsEnumExample
{
    public static void Main()
    {
        Days meetingDays = Days.Monday | Days.Wednesday | Days.Friday;
        Console.WriteLine(meetingDays);
        // Output:
        // Monday, Wednesday, Friday

        Days workingFromHomeDays = Days.Thursday | Days.Friday;
        Console.WriteLine($"Join a meeting by phone on {meetingDays & workingFromHomeDays}");
        // Output:
        // Join a meeting by phone on Friday

        bool isMeetingOnTuesday = (meetingDays & Days.Tuesday) == Days.Tuesday;
        Console.WriteLine($"Is there a meeting on Tuesday: {isMeetingOnTuesday}");
        // Output:
        // Is there a meeting on Tuesday: False

        var a = (Days)37;
        Console.WriteLine(a);
        // Output:
        // Monday, Wednesday, Saturday
    }
}

如需詳細資訊和範例,請參閱 System.FlagsAttribute API 參考頁面和 非獨佔成員和 API 參考頁面的 System.Enum Flags 屬性一節。

System.Enum 類型和列舉條件約束

System.Enum 類型是所有列舉型別的抽象基類。 它提供了多種方法來取得關於列舉類型及其值的資訊。 如需詳細資訊和範例,請參閱 System.Enum API 參考頁面。

您可以在 System.Enum 基類條件 約束中使用 ,以指定類型參數是列舉型別。 任何列舉型別也都滿足 struct 條件約束,用來指定類型參數是不可為 Null 的實值型別。

轉換次數

對於任何列舉類型,列舉類型與其底層整數類型之間存在明確的轉換。 如果您將列舉值 轉換成 其基礎類型,結果就是列舉成員的相關聯整數值。

public enum Season
{
    Spring,
    Summer,
    Autumn,
    Winter
}

public class EnumConversionExample
{
    public static void Main()
    {
        Season a = Season.Autumn;
        Console.WriteLine($"Integral value of {a} is {(int)a}");  // output: Integral value of Autumn is 2

        var b = (Season)1;
        Console.WriteLine(b);  // output: Summer

        var c = (Season)4;
        Console.WriteLine(c);  // output: 4
    }
}

使用此 Enum.IsDefined 方法判斷列舉類型是否包含具有特定相關值的列舉成員。

對於任何列舉類型,分別存在與該類型的箱盒轉換與開System.Enum箱轉換。

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格的下列幾節:

另請參閱