You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

派生类的泛型相等性实现方案问询

实现可继承的强类型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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:18:05