枚举通过为整型常量命名提升代码可读性和类型安全性,适用于表示固定选项(如状态、权限),支持指定值、位运算(配合[Flags]特性)及与字符串、数字的转换,广泛用于避免“魔法数字”并增强维护性。

C# 中,
enum
说到底,定义一个枚举其实很简单,就像给一组相关的数字常量起了个有意义的名字。比如,你想要表示一周的七天,或者一个订单的各种状态,用枚举就比单纯的数字
0, 1, 2...
最基本的定义方式是这样:
public enum DayOfWeek
{
Sunday, // 默认值是0
Monday, // 默认值是1
Tuesday, // 默认值是2
Wednesday,
Thursday,
Friday,
Saturday
}这里,每个枚举成员默认会从 0 开始依次递增赋值。如果你想指定特定的值,或者让它们跳跃,也是可以的:
public enum HttpStatus
{
Ok = 200,
BadRequest = 400,
NotFound = 404,
InternalServerError = 500
}枚举的底层类型默认是
int
byte
short
long
public enum Permissions : byte // 指定底层类型为 byte
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}使用枚举成员时,就像访问一个静态属性一样:
DayOfWeek today = DayOfWeek.Monday;
Console.WriteLine($"今天是 {today}"); // 输出:今天是 Monday
HttpStatus responseStatus = HttpStatus.Ok;
if (responseStatus == HttpStatus.Ok)
{
Console.WriteLine("请求成功!");
}
Permissions userPermissions = Permissions.Read | Permissions.Write; // 位运算,后面会提到
Console.WriteLine($"用户权限:{userPermissions}");我个人觉得,枚举这东西,用好了简直是代码里的“定海神针”,它强制你思考那些离散的、有限的选项,从而避免了各种“魔法数字”在代码里乱飞的尴尬。
枚举的价值,真的不只是给数字起个名那么简单。它在很多场景下都能显著提升代码的可读性和健壮性,减少潜在的 Bug。
首先,最直观的,就是当你有一组固定不变、相互关联的常量时。比如,游戏里的难度等级(简单、中等、困难)、一个程序的不同运行状态(初始化中、运行中、暂停、停止)、或者像前面提到的星期几、HTTP 状态码。用枚举来表示这些,比用一堆
const int EASY = 0;
const int MEDIUM = 1;
DayOfWeek.
0
其次,枚举提供了类型安全性。如果你定义了一个方法,参数类型是
DayOfWeek
DayOfWeek
再者,在
switch
switch
最后,也是比较高级的用法,就是配合
[Flags]
给枚举成员指定值,其实在定义的时候就已经展示过了,直接在成员名后面加上等号和值就行。这在需要将枚举值映射到外部系统(比如数据库字段、API 响应码)时非常常见。比如,你数据库里存的订单状态是
1
2
public enum OrderStatus
{
PendingPayment = 1,
Paid = 2,
Shipped = 3,
Delivered = 4,
Cancelled = 99 // 故意跳跃,表示特殊状态
}这样,当你从数据库读取
1
OrderStatus.PendingPayment
关于位运算,这就要用到
[Flags]
[Flags]
[Flags] // 告诉编译器和运行时,这个枚举可以作为位标志使用
public enum FileAccess
{
None = 0, // 0000
Read = 1, // 0001
Write = 2, // 0010
Execute = 4, // 0100
Delete = 8, // 1000
ReadWrite = Read | Write, // 组合权限
All = Read | Write | Execute | Delete
}有了这个定义,你就可以用位运算符 (
|
&
FileAccess userPermissions = FileAccess.Read | FileAccess.Write; // 用户有读写权限
// 检查是否包含某个权限
if ((userPermissions & FileAccess.Read) == FileAccess.Read)
{
Console.WriteLine("用户有读取权限。");
}
// 检查是否不包含某个权限
if (!userPermissions.HasFlag(FileAccess.Execute)) // HasFlag 方法更易读
{
Console.WriteLine("用户没有执行权限。");
}
// 添加权限
userPermissions |= FileAccess.Delete; // 现在用户也有删除权限了
// 移除权限
userPermissions &= ~FileAccess.Write; // 移除写入权限使用
[Flags]
在实际开发中,枚举值经常需要与字符串(比如用户界面显示)或数字(比如存储到数据库)进行相互转换。C# 为此提供了几种方法。
枚举到数字 (int/byte/etc.): 这是最简单的,直接进行强制类型转换就行了。
DayOfWeek today = DayOfWeek.Wednesday;
int dayValue = (int)today; // dayValue 会是 3
Console.WriteLine($"今天是第 {dayValue} 天 (从0开始计数)");
HttpStatus status = HttpStatus.NotFound;
int statusCode = (int)status; // statusCode 会是 404
Console.WriteLine($"HTTP 状态码:{statusCode}");数字到枚举: 同样是强制类型转换,但这里需要注意一个潜在的问题:如果转换的数字在枚举中没有对应的成员,转换依然会成功,但结果可能不是你预期的有效枚举成员。
int invalidDayValue = 10;
DayOfWeek unknownDay = (DayOfWeek)invalidDayValue; // 编译通过,但 unknownDay 实际上是 10,不在枚举定义范围内
Console.WriteLine($"未知的一天:{unknownDay}"); // 输出:未知的一天:10
int validStatusCode = 200;
HttpStatus validStatus = (HttpStatus)validStatusCode; // validStatus 是 HttpStatus.Ok
Console.WriteLine($"有效状态:{validStatus}");为了避免这种“隐形”的无效值,你通常会配合
Enum.IsDefined
if (Enum.IsDefined(typeof(DayOfWeek), invalidDayValue))
{
DayOfWeek validDay = (DayOfWeek)invalidDayValue;
Console.WriteLine($"转换成功:{validDay}");
}
else
{
Console.WriteLine($"数字 {invalidDayValue} 不是有效的 DayOfWeek 枚举值。");
}枚举到字符串: 直接调用枚举变量的
ToString()
DayOfWeek currentDay = DayOfWeek.Friday;
string dayName = currentDay.ToString(); // dayName 会是 "Friday"
Console.WriteLine($"今天是:{dayName}");字符串到枚举: 这是稍微复杂一点的转换,因为字符串可能不匹配任何枚举成员。主要有两种方法:
Enum.Parse
Enum.TryParse
Enum.Parse
string statusString = "BadRequest";
HttpStatus parsedStatus = (HttpStatus)Enum.Parse(typeof(HttpStatus), statusString);
Console.WriteLine($"解析出的状态:{parsedStatus}"); // 输出:BadRequest
try
{
string invalidString = "NonExistentStatus";
HttpStatus failedStatus = (HttpStatus)Enum.Parse(typeof(HttpStatus), invalidString);
// 这行代码不会执行,因为上面会抛出 ArgumentException
}
catch (ArgumentException ex)
{
Console.WriteLine($"解析失败:{ex.Message}");
}Enum.TryParse
string validStatusString = "NotFound";
HttpStatus resultStatus;
if (Enum.TryParse(validStatusString, out resultStatus))
{
Console.WriteLine($"TryParse 成功解析:{resultStatus}"); // 输出:NotFound
}
else
{
Console.WriteLine($"TryParse 无法解析字符串:{validStatusString}");
}
string anotherInvalidString = "UnknownStatus";
if (Enum.TryParse(anotherInvalidString, out resultStatus))
{
Console.WriteLine($"TryParse 成功解析:{resultStatus}");
}
else
{
Console.WriteLine($"TryParse 无法解析字符串:{anotherInvalidString}"); // 输出:无法解析
}TryParse
if (Enum.TryParse(validStatusString, true, out resultStatus)) // true 表示忽略大小写
{
Console.WriteLine($"忽略大小写解析:{resultStatus}");
}在我的经验里,处理用户输入或者从外部配置文件读取枚举值时,
Enum.TryParse
try-catch
以上就是C#的enum关键字如何定义枚举?怎么使用?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号