enum 基本定义和语法结构
在 C# 中,
enum是一种值类型,用于定义一组命名的常量。它本质是整数(默认
int),但语义更清晰、可读性更强。
定义时必须指定名称,成员默认从 0 开始递增;也可显式赋值,支持跳号、重复值(不推荐):
public enum Status
{
Pending = 0,
Processing = 1,
Completed = 2,
Failed = -1 // 可跨类型赋值,如负数或大整数
}
枚举底层类型可以是 sbyte、
byte、
short、
ushort、
int(默认)、
uint、
long、
ulong,声明时用冒号指定:
enum Priority : byte { Low, Medium, High }
枚举成员名必须是合法标识符,不能带空格或特殊字符;若需显示“User ID”,应配合 [Display]或
[Description]特性处理 不要在枚举里写方法或字段——
enum不支持继承、不能有实例构造函数,也不是类
如何安全地将字符串或数字转为 enum
运行时解析用户输入(如 API 参数、配置文件)时,常见需求是把
string或
int转成对应枚举值。直接强制转换可能抛出异常,必须校验。 用
Enum.TryParse<t></t>最安全:返回
bool表示是否成功,不抛异常
Enum.IsDefined只检查值是否存在,但对字符串不敏感大小写(默认),且无法识别带空格或连字符的别名 避免用
(MyEnum)someInt强转——若
someInt不在枚举范围内,不会报错,但值非法,后续逻辑易出错
string input = "Completed";
if (Enum.TryParse<Status>(input, true, out Status result))
{
Console.WriteLine(result); // 输出 Completed
}
else
{
Console.WriteLine("无效状态");
}使用 [Flags] 特性实现位运算组合
当枚举需要表示「多个状态同时存在」(比如权限、选项集合),应加
[Flags]特性,并确保值是 2 的幂次(1, 2, 4, 8…)。否则
.ToString()和
Enum.ToString()无法正确解析组合值。 未加
[Flags]时,
Permission.Read | Permission.Write的结果调用
.ToString()会输出数字(如
"3"),而非
"Read, Write"每个成员值必须唯一且为 2 的幂;可使用十六进制(
0x10)或左移(
1 )提升可读性判断是否包含某标志用
HasFlag(.NET Core 2.0+ 推荐用
(value & flag) == flag,性能更好)
[Flags]
public enum Permission
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
All = Read | Write | Execute
}
<p>Permission userPerm = Permission.Read | Permission.Write;
Console.WriteLine(userPerm); // 输出 "Read, Write"序列化与反序列化注意事项
JSON 序列化(如 System.Text.Json 或 Newtonsoft.Json)默认按枚举数值序列化,不是名称。这容易引发前后端协作问题:前端看到数字 1,却不知道对应哪个状态。
System.Text.Json:用JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())改为字符串序列化 Newtonsoft.Json:全局设置
JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = { new StringEnumConverter() } };
数据库存储建议存字符串(提高可读性、避免迁移风险),若存整数,务必确保枚举定义稳定——增删成员或改顺序会导致历史数据含义错乱
ASP.NET Core API 默认用 System.Text.Json,不加转换器时,enum字段响应体是数字,前端需硬编码映射,非常脆弱
枚举本身轻量,但它的语义边界一旦被跨层(如 DB → DTO → UI)模糊处理,就容易变成隐性 bug 温床。最稳妥的做法是:定义即冻结、传输即字符串、日志即名称、数据库字段加注释说明取值含义。
