0

given the person class:

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

say, i override the class person`s GetHashCode method:

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

and based on msdn`s instruction, i also need to override the Equality, so i did this:

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

hey, wait, sine i can get the hashcode of the person instance, why not just using hashcode in Equals? like:

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

i googled and found that most Equals() examples are similar with my previous edition of Equals(), so, am i misunderstood something?

any help will appreciated, thx.

4

4 回答 4

3

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

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

于 2013-06-09T09:48:31.570 回答
1

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

例如,让我们上你的课。

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

td;lr:你不能保证两个不相等的对象不会有相同的哈希码。完全没有。(除非它是 abyte或 ashort或 asbyte或 a ushort,但这是技术性的)

于 2013-06-09T09:51:55.940 回答
0

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

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

于 2013-06-10T21:39:45.317 回答
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;
        }
    }
}
于 2013-06-09T09:56:37.963 回答