覆盖一个类型的Equals和GetHashCode,它有'dibs'?

时间:2011-04-09 22:08:46

标签: c# .net equals gethashcode

This question Jon的回答让我意识到这一点甚至存在,所以我很好奇并启动了Visual Studio。


我按照MSDN页面的一个示例,然后创建了我自己的小例子。它如下:

public class Person : IEquatable<Person>
{
    public string IdNumber { get; set; }
    public string Name { get; set; }

    public bool Equals(Person otherPerson)
    {
        if (IdNumber == otherPerson.IdNumber)
            return true;
        else
            return false;
    }

    public override bool Equals(object obj)
    {
        if (obj == null) 
            return base.Equals(obj);

        if (!(obj is Person))
            throw new InvalidCastException("The Object isn't of Type Person.");
        else
            return Equals(obj as Person);
    }

    public override int GetHashCode()
    {
        return IdNumber.GetHashCode();
    }

    public static bool operator ==(Person person1, Person person2)
    {
        return person1.Equals(person2);
    }

    public static bool operator !=(Person person1, Person person2)
    {
        return (!person1.Equals(person2));
    }
}

所以我有几个问题:

  1. 如果Equals方法在处理我的自定义相等性方面做得很好,为什么我也必须覆盖GetHashCode方法呢?

  2. 比较下面的内容时,使用哪个比较器,等于或GetHashCode?

  3. static void Main(string[] args)
    {
        Person sergio = new Person() { IdNumber = "1", Name = "Sergio" };
        Person lucille = new Person() { IdNumber = "2", Name = "Lucille" };
    
        List<Person> people = new List<Person>(){
            sergio,
            lucille
        };
    
        Person lucille2 = new Person() { IdNumber = "2", Name = "Lucille" };
        if (people.Contains(lucille2))
        {
            Console.WriteLine("Already exists.");
        }
    
        Console.ReadKey();
    }
    
    1. 操作员方法到底做了什么?它看起来像某种巫毒黑魔法。

4 个答案:

答案 0 :(得分:7)

  

如果Equals方法在处理我的自定义相等性方面做得很好,为什么我也必须重写GetHashCode方法呢?

这允许您的类型在通过散列工作的集合中使用,例如成为Dictionary<T, U>中的密钥,或存储在HashSet<T>中。

  

比较下面的内容时,使用哪个比较器,Equals或GetHashCode?

GetHashCode不用于比较 - 仅用于散列操作。始终使用等于。

  

操作员方法到底做了什么?它看起来像某种伏都教黑魔法。

这允许您在类型的两个实例上直接使用==。如果没有这个,您将通过引用比较您的类型是否为类,而不是类型中的值。

答案 1 :(得分:3)

GetHashCode的目的是平衡哈希表,而不是确定相等性。当查找散列表的成员时,检查的散列桶由散列码确定,然后由对等确定对象是否在桶中。这就是为什么GetHashCode必须同意平等。

有关详细信息,请参阅我关于此主题的文章:

http://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

答案 2 :(得分:1)

GetHashCode和Equals是两个非常不同的东西。 Equals决定了平等。 GetHashCode返回适合哈希映射的哈希码,但不保证相等。因此,在平等问题上,Equals将是决定平等的方法。

GetHashCode适用于散列集,例如Dictionary。在字典中查找项目时,您将匹配哈希码上的条目,然后匹配Equals

答案 3 :(得分:0)

当您使用哈希表时,GetHashCode仅由MSDN 使用。

如果你需要平等,你只关心Equals。 MSDN建议也实现GetHashCode,因为迟早你可能会在类似哈希的对象(哈希表,哈希映射等)中使用你的对象。

想象一下,对象有1000个字节,你需要一个 fast 方法来确定2个对象之间的相等性 - 你计算哈希键(通过GetHashCode)。如果键不匹配,则对象不同。如果它们匹配,你不能确定它们是否确实相等,你需要用Equal()验证 - 这更贵。

哈希表集合使用此ideea。