列舉型別(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排他成員及旗標屬性

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# 語言規格的下列幾節:

另請參閱