【问题标题】:Overriding the Equals and GetHashCode of a type, which has 'dibs'?覆盖具有“dibs”的类型的 Equals 和 GetHashCode?
【发布时间】:2014-05-07 00:26:12
【问题描述】:

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. 在比较类似下面的内容时,使用哪个比较器,Equals 还是 GetHashCode?​​p>

.

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. operator 方法到底有什么作用?看起来那里正在发生某种伏都教黑魔法。

【问题讨论】:

  • 格式化程序的行为很奇怪。如果有人可以修复它,那就太好了。 :)
  • 如果对象类型错误,不要抛出。如果对象是错误类型,则 它不等于,因此正确答案是“假”。
  • 您能否发布包含该代码的 MSDN 示例的 URL?我会让文档管理员修复它。谢谢!
  • @Eric:在这里:msdn.microsoft.com/en-us/library/ms131190.aspx - 这是IEquatable&lt;T&gt;.Equals 的示例
  • @Eric & @Sergio:我提交了 Connect 错误报告以确保得到纠正:connect.microsoft.com/VisualStudio/feedback/details/658496/…

标签: c# .net equals gethashcode


【解决方案1】:

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

这允许您的类型在通过散列工作的集合中使用,例如作为 Dictionary&lt;T, U&gt; 中的键,或存储在 HashSet&lt;T&gt; 中。

当比较类似下面的内容时,使用哪个比较器,Equals 还是 GetHashCode?​​p>

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

操作符方法到底是做什么的?看起来那里正在发生某种伏都教黑魔法。

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 所以基本上,首先它通过 HashCode 检查对象是否存在于集合中,然后才使用覆盖的 Equals 方法实际比较它。这是正确的吗?
    • 您不会使用哈希键本身“平衡”哈希表,它更多的是执行此操作的哈希算法。散列函数需要快速并且产生尽可能少的冲突(即相同的密钥)。所以要回答这个问题,平衡 = 确保元素尽可能均匀地分布在哈希表中。
    • 那篇文章包含一个规则列表。 Dictionary&lt;TKey, TValue&gt; 等类假定这些规则是正确的。但是,还有其他您可能没有想到的使用GetHashCode 的地方,例如各种 LINQ。当您修改 Equals 而不修改 GetHashCode 时,这些规则最终会被破坏,从而导致依赖于这些规则的代码被破坏。因此,您必须避免使用任何依赖这些规则的代码,或者在修改GetHashCode 的同时不得修改Equals。一般来说,后一种选择更安全,因为GetHashCodeobject 的成员。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      GetHashCode 仅在您使用哈希表时由 MSDN 使用

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

      假设对象有 1000 个字节,您需要一种快速 方法来确定 2 个对象之间的相等性 - 您计算哈希键(通过 GetHashCode)。如果键不匹配,则对象不同。如果它们确实匹配,您无法确定它们是否确实相等,您需要使用 Equal() 进行验证 - 这更昂贵。

      哈希表集合使用这个想法。

      【讨论】:

      • 在某些情况下GetHashCode 可能对相等性测试有用,即使在非散列集合中也是如此。例如,如果不可变树类型支持相等比较(如果叶子节点拥有相同的数据,则它们相等,如果其他节点具有相等的子节点,则它们相等),如果节点缓存其GetHashCode 值,则相等比较可能会大大加快,并在比较孩子之前比较哈希码。如果要比较许多几乎相同的树,即使使用具有 5% 错误匹配的糟糕 GetHashCode 仍然可以将速度提高近 20 倍。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-08
      • 2014-01-03
      • 2012-03-13
      相关资源
      最近更新 更多