为什么不在Equality中使用GetHashCode呢?

时间:2013-06-09 09:46:06

标签: c# override equals hashcode

给出了这个人类:

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;
}
嘿,等等,正弦我能得到人物实例的哈希码,为什么不在Equals中使用哈希码呢?像:

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

我用谷歌搜索,发现大多数Equals()示例与我之前的Equals()版本类似,所以,我误解了什么?

任何帮助都会受到赞赏,thx。

4 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

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

例如,让我们上课。

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

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

答案 2 :(得分:0)

如果你想要一个很好的例子,试着看看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;
        }
    }
}

答案 3 :(得分:0)

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

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