派生类的泛型相等性实现方案问询
实现可继承的强类型Equals方法
看起来你想通过**奇异递归模板模式(CRTP)**来让所有从A<T>派生的类自动继承强类型的Equals实现,这个思路非常棒!我帮你完善代码,确保完全符合你“类型不同返回false,否则比较Value”的需求:
推荐实现(基于IEquatable<T>)
这种方式更直接,派生类无需额外代码就能获得强类型的相等比较能力:
public class A<T> : IEquatable<T> where T : A<T> { protected string Value { get; } public A(string value) { Value = value ?? throw new ArgumentNullException(nameof(value)); } public bool Equals(T? other) { // 处理null情况 if (other is null) return false; // CRTP约束保证other是当前派生类的实例,直接比较Value return Value == other.Value; } // 重写object.Equals,确保与强类型Equals逻辑一致 public override bool Equals(object? obj) { return Equals(obj as T); } // 必须重写GetHashCode,与Equals逻辑配套 public override int GetHashCode() { return Value.GetHashCode(); } // 重载==运算符,符合C#使用习惯 public static bool operator ==(A<T>? left, A<T>? right) { if (left is null) return right is null; return left.Equals(right as T); } // 重载!=运算符 public static bool operator !=(A<T>? left, A<T>? right) { return !(left == right); } }
关键细节说明
- CRTP约束
where T : A<T>:让派生类继承时传入自身作为泛型参数(比如public class B : A<B>),这样基类可以直接操作派生类实例,保证类型匹配。 - 实现
IEquatable<T>:相比IEquatable<A<T>>,这样派生类的Equals调用更直接,无需额外类型转换,类型安全性更高。 - 完整的相等逻辑:同时覆盖了强类型Equals、object.Equals、哈希码和运算符重载,避免出现逻辑不一致的情况。
派生类使用示例
public class B : A<B> { public B(string value) : base(value) { } // 不需要重新编写Equals,自动继承基类实现! } // 测试代码 var b1 = new B("hello"); var b2 = new B("hello"); var b3 = new B("world"); Console.WriteLine(b1.Equals(b2)); // 输出 True Console.WriteLine(b1 == b3); // 输出 False Console.WriteLine(b1.Equals(new object())); // 输出 False(类型不同)
如果你坚持实现IEquatable<A<T>>
如果你的需求是基类实现IEquatable<A<T>>,可以调整代码如下,严格满足“类型不同返回false”的逻辑:
public class A<T> : IEquatable<A<T>> where T : A<T> { protected string Value { get; } public A(string value) { Value = value ?? throw new ArgumentNullException(nameof(value)); } public bool Equals(A<T>? other) { // 先判断是否为null,再检查是否是当前派生类T的实例 if (other is not T concreteInstance) return false; return Value == concreteInstance.Value; } public override bool Equals(object? obj) { return Equals(obj as A<T>); } public override int GetHashCode() { return Value.GetHashCode(); } public static bool operator ==(A<T>? left, A<T>? right) { if (left is null) return right is null; return left.Equals(right); } public static bool operator !=(A<T>? left, A<T>? right) { return !(left == right); } }
这里用other is not T concreteInstance直接判断类型,如果传入的other不是当前派生类的实例(比如其他继承自A<T>的类),会直接返回false,完全符合你的要求。
内容的提问来源于stack exchange,提问作者n0rd
相关产品推荐
相关产品推荐

