简体   繁体   English

GetHashCode应该取决于类型吗?

[英]Should GetHashCode Depend on the Type?

Firstly, I'm using the GetHashCode algorithm described, here . 首先,我在这里使用了描述的GetHashCode算法。 Now, picture the following (contrived) example: 现在,想象下面的(人为的)示例:

class Foo
{
    public Foo(int intValue, double doubleValue)
    {
        this.IntValue = intValue;
        this.DoubleValue = doubleValue;
    }

    public int IntValue { get; private set; }
    public double DoubleValue { get; private set; }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = 17;

            hash = hash * 23 + IntValue.GetHashCode();
            hash = hash * 23 + DoubleValue.GetHashCode();
            return hash;
        }

    }
}

class DerivedFoo : Foo
{
    public DerivedFoo(int intValue, double doubleValue)
       : base(intValue, doubleValue)
    {

    }
}

If I have a Foo and a DerivedFoo with the same values for each of the properties they're going to have the same hash code. 如果我有一个Foo和一个DerivedFoo ,每个属性具有相同的值,那么它们将具有相同的哈希码。 Which means I could have HashSet<Foo> or use the Distinct method in Linq and the two instances would be treated as if they were the same. 这意味着我可以在Linq中使用HashSet<Foo>或使用Distinct方法,这两个实例将被视为相同。

I'm probably just misunderstanding the use of GetHashCode but I would expect these the two instances to have different hash codes. 我可能只是误解了GetHashCode的使用,但我希望这两个实例有不同的哈希码。 Is this an invalid expectation or should GetHashCode use the type in the calculation? 这是一个无效的期望还是GetHashCode应该在计算中使用类型? (Or should DerivedClass also override GetHashCode )? (或者DerivedClass也会覆盖GetHashCode )?

PS I realize there are many, many questions on SO relating to this topic, but I've haven't spotted one that directly answers this question. PS我意识到关于这个主题的SO有很多很多问题,但是我没有发现直接回答这个问题的问题。

GetHashCode() is not supposed to guarantee uniqueness (though it helps for performance if as unique as possible). GetHashCode()不应该保证唯一性(尽管如果尽可能唯一,它有助于提高性能)。

The main rule with GetHashCode() is that equivalent objects must have the same hash code, but that doesn't mean non-equivalent objects can't have the same hash code. GetHashCode()的主要规则是等效对象必须具有相同的哈希代码,但这并不意味着非等效对象不能具有相同的哈希代码。

If two objects have the same hash code, the Equals() method is then invoked to see if they are the same. 如果两个对象具有相同的哈希码,则调用Equals()方法以查看它们是否相同。 Since the types are different (depending on how you coded your Equals overload of course) they will not be equal and thus it will be fine. 由于类型不同(取决于你如何编码你的Equals过载),它们将不相等,因此它会没问题。

Even if you had a different hash code algorithm for each type, there's still always a chance of a collision, thus the need for the Equals() check as well. 即使你有一个不同的散列码算法为每种类型的,还是有总是碰撞的机会,因此,需要对Equals()检查为好。

Now given your example above, you do not implement Equals() this will make every object distinct regardless of the hash code because the default implementation of Equals() from object is a reference equality check. 现在给出上面的示例,您不实现Equals()这将使每个对象都不同,无论哈希代码如何,因为objectEquals()的默认实现是引用相等性检查。

If you haven't, go ahead and override Equals() for each of your types as well (they can inherit your implementation of GetHashCode() if you like, or have new ones) and there you can make sure that the type of the compare-to object are the same before declaring them equal. 如果还没有,请继续为每个类型重写Equals() GetHashCode()如果你愿意,可以继承你的GetHashCode()实现,或者有新的类型),你可以确保它的类型在声明它们相等之前,compare-to对象是相同的。 And make sure Equals() and GetHashCode() are always implemented so that: 并确保始终实现Equals()GetHashCode() ,以便:

  • Objects that are Equals() must have same GetHashCode() results. Equals()对象必须具有相同的GetHashCode()结果。
  • Objects with different GetHashCode() must not be Equals() . 具有不同GetHashCode()对象不能Equals()

The two instances do not need to have different hash codes. 这两个实例不需要具有不同的哈希码。 The results of GetHashCode are not assumed by the HashSet or other framework classes, because there can be collisions even within a type. HashSet或其他框架类不假定GetHashCode的结果,因为即使在类型中也可能发生冲突。 GetHashCode is simply used to determine the location within the hash table to store the item. GetHashCode仅用于确定哈希表中用于存储项目的位置。 If there is a collision within the HashSet, it then falls back on the result of the Equals method to determine the unique match. 如果HashSet中存在冲突,则它会回退到Equals方法的结果以确定唯一匹配。 This means that whever you implement GetHashCode, you should also implement Equals (and check that the types match). 这意味着当您实现GetHashCode时,您还应该实现Equals(并检查类型是否匹配)。 Similarly, whenever you implement Equals, you should also implement GetHashCode. 同样,每当实现Equals时,您还应该实现GetHashCode。 See a good explanation by Eric Lippert here . 请看Eric Lippert 在这里的一个很好的解释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM