Skip to content

C# - 枚举

枚举,即 enum,是一种值类型(value type),它定义了一组命名常量。枚举允许您使用描述性名称代替“魔术数字(magic numbers)”或字符串,从而使您的代码更具可读性和可维护性。

当您拥有一组离散的相关值时,例如一周中的天数、状态机中的状态(如 Pending、Processing、Completed),或用户角色(Admin、Member、Guest),请使用枚举。

您可以使用 enum 关键字声明枚举。默认情况下,枚举的基础类型是 int,并且第一个成员的值为 0,每个后续成员递增 1。

public enum DayOfWeek
{
Sunday, // 0
Monday, // 1
Tuesday, // 2
Wednesday, // 3
Thursday, // 4
Friday, // 5
Saturday // 6
}

您可以声明一个枚举类型的变量,并为其赋值一个枚举成员。这提供了强类型安全(strong type safety)。

// Using top-level statements (modern C#)
DayOfWeek today = DayOfWeek.Wednesday;
Console.WriteLine($"Today is {today}.");
// To get the integer value, you must cast it explicitly.
int dayValue = (int)today;
Console.WriteLine($"Numeric value for {today} is {dayValue}.");
public enum DayOfWeek
{
Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
}

当上述代码执行时,将产生以下结果:

Today is Wednesday.
Numeric value for Wednesday is 3.

您可以自定义枚举成员的整数值。为了性能或存储优化,您还可以将底层类型更改为除 char 之外的任何整型(integral type),例如 byte 或 long。

// Using a 'byte' for efficiency and specifying custom values
public enum HttpStatus : byte
{
OK = 200,
NotFound = 44, // Values don't have to be contiguous
InternalServerError = 50
}
HttpStatus status = HttpStatus.OK;
Console.WriteLine($"Status: {status} (Value: {(byte)status})");

枚举非常适合 switch 逻辑。现代 C# 引入了 switch 表达式(switch expressions),它提供了比传统 switch 语句更简洁和易读的语法。

DayOfWeek today = DayOfWeek.Friday;
string message = today switch
{
DayOfWeek.Saturday or DayOfWeek.Sunday => "It's the weekend!",
DayOfWeek.Friday => "It's almost the weekend!",
_ => "It's a weekday."
};
Console.WriteLine(message);
// This will output: It's almost the weekend!

使用 [Flags] 特性的位标志(Bit Flags)

Section titled “使用 [Flags] 特性的位标志(Bit Flags)”

通过添加 [Flags] 特性并分配 2 的幂作为值,您可以使用位运算符(bitwise operators)组合枚举成员。这对于表示一组选项或权限非常有用。

[Flags]
public enum Permissions
{
None = 0, // 0000
Read = 1, // 0001
Write = 2, // 0010
Execute = 4, // 0100
All = Read | Write | Execute
}
// Assign multiple permissions using the bitwise OR operator
Permissions userPermissions = Permissions.Read | Permissions.Write;
Console.WriteLine($"User permissions: {userPermissions}");
// Check for a specific permission using HasFlag()
bool canWrite = userPermissions.HasFlag(Permissions.Write);
Console.WriteLine($"User has Write permission? {canWrite}"); // True
bool canExecute = userPermissions.HasFlag(Permissions.Execute);
Console.WriteLine($"User has Execute permission? {canExecute}"); // False

将字符串或整数转换为枚举值是很常见的,例如从配置文件或数据库中读取时。使用 Enum.TryParse 是最安全的方法,因为它能防止因无效输入而引发异常。

// Safely parsing a string to an enum
string statusInput = "Completed";
if (Enum.TryParse<OrderStatus>(statusInput, out OrderStatus status))
{
Console.WriteLine($"Successfully parsed string: {status}");
}
else
{
Console.WriteLine($"'{statusInput}' is not a valid order status.");
}
// Converting an integer to an enum
int statusCode = 2;
OrderStatus statusFromInt = (OrderStatus)statusCode;
Console.WriteLine($"Converted from integer: {statusFromInt}");
public enum OrderStatus { Pending, Processing, Shipped, Completed }
  • 错误:将未定义的整数转换为枚举。这不会引发错误,但可能导致无效状态。在转换之前可以使用 Enum.IsDefined 来检查有效性。
  • 最佳实践:为枚举使用单数名称(例如 OrderStatus,而不是 OrderStatuses),因为该类型的变量只包含一个单一值。
  • 最佳实践:使用 Enum.TryParse 而不是 Enum.Parse 来优雅地处理无效字符串输入,而无需 try-catch 块。