C#中如何让同值的两个枚举成员比较时判定为不相等?
核心结论
原生C#枚举完全无法实现你要的效果:同底层值的两个枚举项,在CLR运行时层面没有任何身份差异,只要整数值一致,==、Equals()、CompareTo()必然返回相等,没有任何配置或特性可以修改这个运行时硬逻辑。
问题根因
C#枚举本质是底层整数类型(默认是int)的强类型语法糖,你写MyEnum.A1和MyEnum.A2的时候,编译后实际存的就是整数0,运行时不会保留你写的成员名信息,内存里两个值没有任何区别。你现在的代码里传A2进第一个if分支,不是比较方法的问题,是运行时从根上就分不清这两个值。甚至你对同值的枚举项调用ToString(),返回的名字都可能因为反射枚举成员的顺序变化出现随机结果,完全不可靠。
最佳实现方案
放弃用原生枚举存同值不同身份的项,用只读结构体自定义模拟枚举,既保留值类型性能、和int转换的能力,又能实现同值不同项的相等判断区分:
public readonly struct MyEnum : IEquatable<MyEnum> { private readonly int _backingValue; private readonly string _identity; private MyEnum(int value, string identity) { _backingValue = value; _identity = identity; } // 定义枚举成员,两个成员底层值都是0,身份不同 public static readonly MyEnum A1 = new(0, nameof(A1)); public static readonly MyEnum A2 = new(0, nameof(A2)); // 隐式转int,直接返回统一的底层值 public static implicit operator int(MyEnum e) => e._backingValue; // 相等比较只看唯一身份,同值不同身份判定为不相等 public bool Equals(MyEnum other) => _identity == other._identity; public override bool Equals(object? obj) => obj is MyEnum other && Equals(other); public override int GetHashCode() => _identity.GetHashCode(); public static bool operator ==(MyEnum left, MyEnum right) => left.Equals(right); public static bool operator !=(MyEnum left, MyEnum right) => !left.Equals(right); }
这个实现可以直接复用你原来的业务代码逻辑:
- 判断
enumInstance == MyEnum.A1时,传入A2会正确返回false,不会进错分支 - 执行
return (int)enumInstance时,A1和A2都会返回0,满足你取统一整数值的需求 - 本身是值类型,没有堆分配开销,性能和原生枚举基本一致
避坑提醒
不要尝试用自定义扩展方法、加特性、反射拦截这类方案绕原生枚举的限制:你无法重载原生枚举的==运算符,CLR永远会优先按底层整数做比较,只要有一处代码不小心用了原生比较逻辑就会出隐蔽bug,维护成本极高。
内容的提问来源于stack exchange,提问作者MarkusAnd
相关产品推荐
相关产品推荐

