【问题标题】:why not just using GetHashCode in Equality? [duplicate]为什么不在 Equality 中使用 GetHashCode? [复制]
【发布时间】:2013-06-09 09:46:05
【问题描述】:

给定人员类:

class person
{
    public string name;
    public int age;
}

说,我重写了类人的 GetHashCode 方法:

 public override int GetHashCode()
 {
     unchecked
     {
          hashCode = 17;
          // ...some code here...
     }
     return hashCode;
 }

根据 msdn 的指令,我还需要重写 Equality,所以我这样做了:

public override bool Equals(object obj)
{
    // ...something like: 
    return this.name == (person)obj.name && this.age ==(person)obj.age;
}

嘿,等等,我可以得到 person 实例的哈希码,为什么不在 Equals 中使用哈希码呢?喜欢:

public override bool Equals(object obj)
{
    return this.GetHashCode() == (person)obj.GetHashCode();
}

我搜索了一下,发现大多数 Equals() 示例与我之前版本的 Equals() 相似,所以,我误解了什么吗?

任何帮助将不胜感激,谢谢。

【问题讨论】:

  • 你应该阅读我的文章。搜索 gethashcode 的指南和规则。
  • 哇~我搜索并找到了这个link希望这能帮助其他有同样疑问的人:)

标签: c# overriding equals hashcode


【解决方案1】:

不保证两个不相等的对象具有不相等的哈希码(这称为冲突)。这就是 MSDN 所说的:

如果两个对象比较相等,则每个对象的 GetHashCode 方法必须返回相同的值。但是,如果两个对象比较不相等,则两个对象的 GetHashCode 方法不必返回不同的值。

【讨论】:

    【解决方案2】:

    这是因为有比哈希码更多的可能性。

    例如,让我们来上课。

    您已经遇到问题了,因为年龄范围与int 的范围相同。当然,这可以消除:只需使用 byte 代替。尽管如此,我们还是有一个问题:字符串。 .NET 字符串是 Unicode (UTF-16),因此每个字母有 65,536 个可能的字符。之后,它迅速升级......两个字符串最多可以有 65,536 ^ 2 个字符,即 4,294,967,296 (uint.MaxValue) 可能性。太多了,而且只有两个字符。

    td;lr:你不能保证两个不相等的对象不会有相同的哈希码。完全没有。 (除非是 byteshortsbyteushort,但这是技术性问题)

    【讨论】:

    • 您的字符串分析错误。它真的是 string.length 的 65536 次幂。更好的思考方式是,长度为 2 的字符串中有 4 个字节,哈希码中有 4 个字节,因此长度为 2 之后肯定会发生冲突。
    • 我错在 UTF-32 和 UTF-16 之间混淆了。你是对的。
    【解决方案3】:

    如果你想要一个好的例子,试着站在 Resharper 一边。

    public class Person : IEquatable<Person>
    {
        public string Name { get; set; }
        public int Age { get; set; }
    
        public bool Equals(Person other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return string.Equals(Name, other.Name) && Age == other.Age;
        }
    
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((Person) obj);
        }
    
        public override int GetHashCode()
        {
            unchecked
            {
                return ((Name != null ? Name.GetHashCode() : 0) * 397) ^ Age;
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      GetHashCode 背后的想法是,如果知道两个对象具有不同的哈希码,则无需查看它们就可以安全地假设它们不相等。只有当两个对象的哈希码匹配时,才有必要进一步检查它们。如果有一个对象集合,其哈希码不可能与给定对象匹配(例如,因为集合中的所有对象的哈希码都以 4591 结尾,而给定对象的哈希码以 2011 结尾),则无需检查任何集合中的对象知道它们都不可能匹配给定的对象。

      发现哈希码与给定对象的哈希码匹配的对象的正确编写的代码应该确定这些对象可能匹配,但也可能不匹配,并且应该详细扫描对象以找出它们是否真的匹配。如果哈希码匹配但对象不匹配,则哈希码匹配的唯一结果应该是增加发现对象不同所需的时间。如果百万分之一的比较产生错误匹配,则预先检查哈希码可以将详细比较的数量减少一百万倍。相比之下,如果散列函数几乎没有那么好,并且千分之一的比较产生错误匹配,则预先检查散列码将“仅”将详细比较的数量减少一千倍。当然,即使一千倍的加速不如一百万倍的加速,它仍然可能比没有加速要好得多。

      【讨论】:

        猜你喜欢
        • 2011-06-11
        • 2011-09-12
        • 2022-07-27
        • 1970-01-01
        • 2013-08-06
        • 1970-01-01
        • 2010-09-11
        • 1970-01-01
        相关资源
        最近更新 更多