应使用 Enum.TryParse 而非 Enum.Parse 处理用户输入,因其返回 bool 且不抛异常;注意 ignoreCase 参数控制大小写敏感;空格、连字符需预处理或字典映射;culture 对名称解析无效;高频场景建议缓存映射。
Enum.Parse 会直接抛异常,别用它处理用户输入
只要字符串和枚举值对不上,enum.parse 就扔 argumentexception 或 formatexception —— 这在解析表单、配置项、api 参数时非常危险。真实场景里,你根本不能假设传进来的字符串一定合法。
- 用
Enum.TryParse替代,它返回bool表示是否成功,不抛异常 - 注意第三个参数
ignoreCase:设为true才支持大小写不敏感匹配(默认是false) - 如果输入是空字符串或 null,
TryParse直接返回false,不会崩,但你要自己决定是否允许默认值
bool success = Enum.TryParse<loglevel>("warn", true, out LogLevel level); // true</loglevel>
字符串含空格或连字符时,Enum.TryParse 默认失败
C# 枚举名本身不支持空格和中划线,但业务里常遇到 "log-level"、"high priority" 这类描述性字符串。此时 Enum.TryParse 按字面匹配,肯定失败。
- 别改枚举名去迁就字符串(比如加
[Display(Name = "High Priority")]),那只是 UI 层修饰,不影响Parse行为 - 需要映射时,用字典预存关系:
Dictionary,或者用Enum.GetNames+String.Replace做标准化(如把"-"全转成"_") - 若必须走反射+特性方案,优先用
GetCustomAttributes,而非硬编码字符串查找()
Enum.Parse 的 culture 参数几乎没用,别被文档误导
文档里说 Enum.Parse(Type, string, IFormatProvider) 支持文化信息,但实际只影响数字型枚举(比如 enum E { A = 1 };),对名称匹配完全无效。中文系统下传 "A" 给 Parse,无论 culture 设成 zh-CN 还是 en-US,结果都一样。
- 名称解析永远按 C# 标识符规则,和 locale 无关
- 唯一可能受 culture 影响的,是把数字字符串(如
"1")转成枚举值,但这种用法本身就容易出错,应避免 - 如果你真在处理带本地化数字的场景,先用
int.TryParse+ culture 解析成整数,再显式转枚举更可控
性能差的不是 Parse,而是反复调用没缓存的 TryParse
单次 Enum.TryParse 开销很小,但高频场景(比如日志批量解析、消息队列消费)里,如果每次都在内部重复查 Enum.GetNames 和字符串比较,就会成为瓶颈。
- .NET 6+ 已对
TryParse做了静态缓存优化,但老版本(.NET Framework / .NET Core 3.1)没有 - 若需兼容旧框架,且转换频次高,建议自行缓存映射字典,初始化一次,复用到底
- 缓存 key 用
typeof(T).FullName+ignoreCase组合,避免不同枚举类型冲突
最易被忽略的一点:枚举类型本身是静态的,但它的名称集合可能被 JIT 或 AOT 编译器优化掉部分反射路径——所以别在热路径里无脑依赖 GetNames 做运行时推导。











