首页 文章

为什么不在Equality中使用GetHashCode呢? [重复]

提问于
浏览
0

这个问题在这里已有答案:

给人类:

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();
}

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

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

4 回答

  • 3

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

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

  • 1

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

    例如,让我们上课 .

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

    td;lr :你可以't guarantee that two objects that are not equal will not have the same hashcode. At all. (unless it'是 byteshortsbyteushort ,但这是技术性的)

  • 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;
            }
        }
    }
    
  • 0

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

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

相关问题