簡體   English   中英

GetHashCode應該取決於類型嗎?

[英]Should GetHashCode Depend on the Type?

首先,我在這里使用了描述的GetHashCode算法。 現在,想象下面的(人為的)示例:

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)
    {

    }
}

如果我有一個Foo和一個DerivedFoo ,每個屬性具有相同的值,那么它們將具有相同的哈希碼。 這意味着我可以在Linq中使用HashSet<Foo>或使用Distinct方法,這兩個實例將被視為相同。

我可能只是誤解了GetHashCode的使用,但我希望這兩個實例有不同的哈希碼。 這是一個無效的期望還是GetHashCode應該在計算中使用類型? (或者DerivedClass也會覆蓋GetHashCode )?

PS我意識到關於這個主題的SO有很多很多問題,但是我沒有發現直接回答這個問題的問題。

GetHashCode()不應該保證唯一性(盡管如果盡可能唯一,它有助於提高性能)。

GetHashCode()的主要規則是等效對象必須具有相同的哈希代碼,但這並不意味着非等效對象不能具有相同的哈希代碼。

如果兩個對象具有相同的哈希碼,則調用Equals()方法以查看它們是否相同。 由於類型不同(取決於你如何編碼你的Equals過載),它們將不相等,因此它會沒問題。

即使你有一個不同的散列碼算法為每種類型的,還是有總是碰撞的機會,因此,需要對Equals()檢查為好。

現在給出上面的示例,您不實現Equals()這將使每個對象都不同,無論哈希代碼如何,因為objectEquals()的默認實現是引用相等性檢查。

如果還沒有,請繼續為每個類型重寫Equals() GetHashCode()如果你願意,可以繼承你的GetHashCode()實現,或者有新的類型),你可以確保它的類型在聲明它們相等之前,compare-to對象是相同的。 並確保始終實現Equals()GetHashCode() ,以便:

  • Equals()對象必須具有相同的GetHashCode()結果。
  • 具有不同GetHashCode()對象不能Equals()

這兩個實例不需要具有不同的哈希碼。 HashSet或其他框架類不假定GetHashCode的結果,因為即使在類型中也可能發生沖突。 GetHashCode僅用於確定哈希表中用於存儲項目的位置。 如果HashSet中存在沖突,則它會回退到Equals方法的結果以確定唯一匹配。 這意味着當您實現GetHashCode時,您還應該實現Equals(並檢查類型是否匹配)。 同樣,每當實現Equals時,您還應該實現GetHashCode。 請看Eric Lippert 在這里的一個很好的解釋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM