【问题标题】:Does C# HashSet check duplicate by Equals then by GetHashCode?C# HashSet 是否通过 Equals 然后通过 GetHashCode 检查重复?
【发布时间】:2016-04-16 13:45:46
【问题描述】:

只是想让有人确认我的想法,我在 Foo 类中尝试了覆盖 EqualsGetHashCode 的不同组合:

class Foo
{
    static int n;
    public override bool Equals(object obj)
    {
        return true;
        //return false;
    }
    public override int GetHashCode()
    {
        return 0;
        //return n++;
    }
}

然后测试结果显示:

    static void Main(string[] args)
    {
        HashSet<Foo> set = new HashSet<Foo>();
        Foo f1 = new Foo();
        Foo f2 = new Foo();

        Console.WriteLine(f1.Equals(f2));
        set.Add(f1);
        Console.WriteLine(set.Contains(f2));
        Console.ReadLine();
    }
  1. 当 Equals 为真时,Contains 由 GetHashCode 确定;
  2. 当 Equals 为 false 时,Contains 始终为 false。

所以 包含 由 Equals 确定,然后由 GetHashCode 确定,对吗?

【问题讨论】:

  • 您可以通过在每个被覆盖的方法中添加Console.WriteLine 来轻松确认您的想法,以查看它们出现的顺序。

标签: c# .net dictionary hashset


【解决方案1】:

反过来。首先调用GetHashCode()。这用于给出哈希码(因此得名),用于确定对象应在内部存储的位置。

无法保证哈希码是唯一的(此外,它会进一步减少),因此可能会有多个对象存储有相同的哈希(越多,性能越差,但这是另一回事)。所以在找到可能的匹配后,Equals 用于确认匹配。

所以Contains 首先依赖于GetHashCode(),然后依赖于Equals()

这两者协同工作就是为什么如果你覆盖另一个,你必须总是覆盖一个,并且总是覆盖你的GetHashCode(),这样任何两个会相互考虑的对象Equal()都将具有相同的代码.

【讨论】:

  • 确保两个认为彼此相等的对象具有相同哈希码的最简单方法通常是让您的Equals() 方法调用您的GetHashCode() 方法。
  • 提供来自相关 MSDN 文档(和链接)的报价将是更好地记录您的帖子的理想选择。这也应该有助于其他人验证这是记录在案的行为,而不是在不同的环境/实现(例如 Mono)下可能不同的实现细节。
  • @JoelCoehoorn 这完全是假的。两个相等的对象必须有相同的哈希码,但两个不同的对象可以有相同的哈希码
  • @JoelCoehoorn 假设long 像这样实现了Equalslong 具有比可能的哈希码更多的值,因此比较相等的不同值将是不可避免的。同意 Jcl,这是非常错误的,你真的不明白哈希码应该如何工作(并且工作)。
  • @Enigmativity 这是错误的。对象在用作键时不得以影响其GetHashCode(或Equals)的方式更改,但如果对象以其他方式更改其被认为等于的值,则哈希码必须改变。当然,这两个要求可能会发生冲突,解决它的最简单方法是仅使用不可变对象作为键,因此永远不会出现当它们发生变化时该怎么做的问题。
猜你喜欢
  • 2015-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 2013-03-26
  • 2020-12-25
相关资源
最近更新 更多