使用枚举包装类时,如何在C#中恢复switch语句的使用?
C# 自定义枚举包装类在switch中使用的问题解决
你参考微软官方的枚举包装类(Enumeration基类)实现了枚举值自定义ToString()名称的功能,但在switch语句中使用该类型时遇到了"A constant value is expected"的错误——因为这些包装类的实例是readonly static的对象,无法用const修饰,所以没法直接作为case的常量条件。
问题示例代码
var a = CardType.Amex; switch(a) { case CardType.Amex: { } break; }
根本原因
C#的switch语句要求case标签必须是编译期常量表达式,而自定义枚举包装类的静态实例是运行时初始化的对象,不属于编译期常量,因此不能直接放在case后面作为匹配条件。
可行解决方案
1. 基于包装类的底层常量值做switch
枚举包装类通常会包含一个底层标识(比如int类型的Id),把这个Id定义为const常量,然后switch时匹配这个值:
// 先在CardType类中定义常量Id public class CardType : Enumeration { public const int AmexId = 1; public const int VisaId = 2; public static readonly CardType Amex = new CardType(AmexId, "American Express"); public static readonly CardType Visa = new CardType(VisaId, "Visa"); // 基类构造函数及其他成员... } // 使用时的switch代码 var a = CardType.Amex; switch(a.Id) { case CardType.AmexId: // 处理Amex逻辑 break; case CardType.VisaId: // 处理Visa逻辑 break; }
2. 使用C# 7.0+的模式匹配(when条件)
借助模式匹配的when子句,直接比较实例的引用相等性(因为包装类的实例是readonly static的,引用相等是可靠的):
var a = CardType.Amex; switch(a) { case var ct when ct == CardType.Amex: // 处理Amex逻辑 break; case var ct when ct == CardType.Visa: // 处理Visa逻辑 break; }
如果你的项目使用C# 9.0及以上,写法可以更简洁:
switch(a) { case CardType ct when ct == CardType.Amex: // 处理逻辑 break; }
3. 确保包装类正确重载相等运算符
枚举包装类基类(如微软文档中的Enumeration)通常已经重载了Equals和==运算符,确保实例比较的是底层标识而非引用,这样上面的模式匹配逻辑会更可靠。
总结
C#并非完全不能对自定义类型使用switch,只是不能直接将自定义类型的实例作为case的常量标签。通过上述两种方法,你可以顺畅地在switch中使用自定义枚举包装类。
内容的提问来源于stack exchange,提问作者DragonGamer
相关产品推荐
相关产品推荐

