[英]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()
這將使每個對象都不同,無論哈希代碼如何,因為object
的Equals()
的默認實現是引用相等性檢查。
如果還沒有,請繼續為每個類型重寫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.