【问题标题】:GetHashCode EqualityGetHashCode 等式
【发布时间】:2010-10-12 05:55:07
【问题描述】:

我想知道这个,所以我想我会问它。

您将看到的大多数地方使用与 GetHashCode 相同的语义逻辑来覆盖 Equals 以实现成员相等...但是它们通常使用不同的实现:

    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }
        var other = (MyType)obj;
        if (other.Prop1 != Prop1)
        {
            return false;
        }
        return true;
    }

    public override int GetHashCode()
    {
        int hash = -657803396;
        num ^= Prop1.GetHashCode();
        return num;
    }

如果您正在为您的类型实现成员相等(假设存储在字典中),为什么不直接覆盖 GetHashCode 然后为 Equals 执行类似的操作:

    public override bool Equals(object obj)
    {
        return this.HashEqualsAndIsSameType(obj);
    }

    public static bool HashEquals(this object source, object obj)
    {
        if (source != null && obj != null)
        {
            return source.GetHashCode() == obj.GetHashCode();
        }
        if (source != null || obj != null)
        {
            return false;
        }
        return true;
    }

    public static bool HashEqualsAndIsSameType<T>(this T source, object obj)
    {
        return (obj == null || obj.GetType() == typeof(T)) && source.HashEquals(obj);
    }

【问题讨论】:

    标签: c# .net gethashcode


    【解决方案1】:

    因为存在真正的冲突风险。哈希码不是唯一的。他们可以(当不同时)证明不平等,但永远不能证明平等。寻找物品时:

    • 获取哈希码
    • 如果哈希码不同,则对象不同;丢弃它
    • 如果哈希码相同,检查等于:
    • 如果 Equals 报告 true 它们是相同的
    • 否则丢弃

    考虑long...因为哈希码是int,很容易看出有很多很多的冲突。

    【讨论】:

    • 那么,您如何建议使用最少的重复成员引用来实现成员 GetHashCode/Equals?这种重复可能会导致意外遗漏并导致重大问题(这就是我今天提出问题的原因)。另外,如果我们确实想要一个对象的唯一校验和怎么办。是否已经存在一个好的接口来定义一个类型提供计算校验和的能力?
    • @jeff 你很少需要这样做,但是像 resharper 这样的工具会为你做这件事
    • 一个例子 - 离线乐观缓存和/或锁定各种类型的对象(换句话说,数据库中的表上没有列可以用版本 id 标记)。客户端和服务器都需要一种计算唯一的哈希或校验和(你会称之为)的方法,因此如果客户端将过时的版本发送回服务器,服务器知道不保存它并抛出一个例外。为此,您将如何计算哈希/校验和?
    • 通常如果检查equals,equals应该先比较hash码,如果相同,再比较实际值。无需先手动比较哈希码。
    【解决方案2】:

    散列不是一对一的,你可以有多个不同的值,它们散列到相同的值,但应该比较为不相等。因此,您不能真正根据 GetHashCode 实现 Equals。这就是哈希表中存在冲突的原因,也是哈希表查找必须涉及对 GetHashCode 和 Equals 的调用的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-03
      • 1970-01-01
      • 2019-06-12
      • 2012-10-23
      • 1970-01-01
      相关资源
      最近更新 更多