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

LINQ Distinct未调用IEquatable<T>.Equals实现的问题求解

问题原因

你的问题是GetHashCode方法实现不符合规范,同时缺少非泛型Equals(object)方法的重写,导致基于哈希的集合操作(包括Distinct)无法正确判定相等性。

为什么Contains正常但Distinct失效

  • List<T>.Contains的内部逻辑是遍历列表元素,逐个调用Equals方法比对,不需要预先校验对象哈希码,所以哪怕GetHashCode实现错误也不影响它的执行结果。
  • Distinct属于基于哈希的操作,执行逻辑是先调用对象的GetHashCode方法获取哈希值:如果两个对象的哈希值不同,会直接判定为不相等,根本不会触发后续的Equals调用;只有哈希值相同时,才会调用Equals做最终的相等性校验。

你代码里的两个核心错误

  1. GetHashCode实现完全错误
    你写的public override int GetHashCode() => base.GetHashCode + this.Id;存在两个问题:
  • 语法错误:base.GetHashCode是方法组,调用需要加括号,实际运行会报错。
  • 逻辑错误:就算补全括号变成base.GetHashCode(),调用的是基类object的GetHashCode实现,该实现默认基于对象的内存地址生成哈希值,你两个new出来的Test实例哪怕Id完全相同,内存地址不同,生成的哈希值也一定不同,Distinct会直接判定为两个不同对象,不会触发你自定义的Equals逻辑。
  1. 缺少object.Equals的重写
    重写IEquatable<T>.Equals的同时必须配套重写非泛型的Equals(object)方法,这是.NET相等性实现的强制规范,否则部分场景下的相等比较依然会走默认的引用比较逻辑。

正确实现示例

public class Test : IEquatable<Test>
{
    public int Id { get; init; }

    public bool Equals(Test other)
    {
        if (ReferenceEquals(null, other))
            return false;
        if (ReferenceEquals(this, other))
            return true;
        if (GetType() != other.GetType())
            return false;
        return Id == other.Id;
    }

    // 新增重写非泛型Equals方法
    public override bool Equals(object obj)
    {
        return Equals(obj as Test);
    }

    // 修正GetHashCode,仅使用参与相等比较的不可变属性生成哈希值
    public override int GetHashCode()
    {
        // 单字段可直接返回字段的哈希码,多字段推荐用HashCode.Combine
        return HashCode.Combine(Id);
    }

    // 可选:配套重写相等运算符,符合.NET开发规范
    public static bool operator ==(Test left, Test right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Test left, Test right)
    {
        return !Equals(left, right);
    }
}

注意事项

GetHashCode的实现必须满足以下规则:

  • 相等的对象必须返回相同的哈希码。
  • 哈希码的生成只能依赖参与相等比较的、不可变的字段/属性,避免对象修改后哈希码变化导致哈希集合行为异常。
  • 不需要保证不同对象返回的哈希码一定不同,只要相等对象哈希码相同即可,哈希冲突由后续的Equals调用处理。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:36:08