枚举类型(C# 参考)

枚举类型(或枚举类型)是由基础整型数值类型的一组命名常量定义的值类型。 若要定义枚举类型,请使用 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 分配了 port20,但没有 GpioPort 具有该值的成员。 该方法 Enum.IsDefined 确认这些枚举值无效。

存在此隐式转换,因为 0 位模式是所有结构类型的默认值,包括所有枚举类型。 但是,它可以在代码中引入 bug。 为避免这些问题:

  • 你几乎应该始终在枚举中定义具有值 0 的成员。
  • 用于 Enum.IsDefined 在从数值类型转换时验证枚举值。
  • 使用可能隐式转换为枚举类型的数值参数时,请谨慎。

可以使用枚举类型来表示一组互斥值或选项组合中的选项。 若要表示选项的组合,请将枚举类型定义为位标志。

作为位标志的枚举类型

如果希望枚举类型表示选项的组合,请为这些选项定义枚举成员,以便单个选择是位字段。 也就是说,这些枚举成员的关联值应该是 2 的幂。 然后,可以使用 按位逻辑运算符 |& 分别组合选项或相交选项组合。 若要指示枚举类型声明位字段,请向其应用 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# 语言规范的以下部分:

另请参阅