[英]How to write a good GetHashCode() implementation for a class that is compared by value?
[英]Why does initial hash value in GetHashCode() implementation generated for anonymous class depend on property names?
在為匿名類生成GetHashCode()
實現時,Roslyn根據屬性名稱計算初始哈希值。 例如,為其生成的類
var x = new { Int = 42, Text = "42" };
將有以下GetHashCode()
方法:
public override in GetHashCode()
{
int hash = 339055328;
hash = hash * -1521134295 + EqualityComparer<int>.Default.GetHashCode( Int );
hash = hash * -1521134295 + EqualityComparer<string>.Default.GetHashCode( Text );
return hash;
}
但是,如果我們更改屬性名稱,則初始值會更改:
var x = new { Int2 = 42, Text2 = "42" };
public override in GetHashCode()
{
int hash = 605502342;
hash = hash * -1521134295 + EqualityComparer<int>.Default.GetHashCode( Int2 );
hash = hash * -1521134295 + EqualityComparer<string>.Default.GetHashCode( Text2 );
return hash;
}
這種行為背后的原因是什么? 只選擇一個大的[prime?]數字並將其用於所有匿名類都有問題嗎?
只選擇一個大的[prime?]數字並將其用於所有匿名類都有問題嗎?
這樣做沒有任何問題,只會產生效率較低的價值。
GetHashCode
實現的目標是為不相等的值返回不同的結果。 當在基於散列的集合(例如Dictionary<TKey, TValue>
)中使用這些值時,這可以減少沖突的幾率。
如果匿名值表示不同的類型,則永遠不能等於另一個匿名值。 匿名值的類型由屬性的形狀定義:
在這些特征中的任何一個上不同的兩個匿名值表示不同的類型,因此永遠不能是相等的值。
鑒於這是真的,編譯器生成GetHashCode
實現是有意義的,這些實現往往會為不同類型返回不同的值。 這就是編譯器在計算初始哈希時包含屬性名稱的原因。
除非羅斯林團隊的人員加強,否則我們只能推測。 我會以同樣的方式做到這一點。 對每個匿名類型使用不同的種子似乎是在哈希碼中具有更多隨機性的有用方法。 例如,它會導致new { a = 1 }.GetHashCode() != new { b = 1 }.GetHashCode()
為true。
我也想知道是否存在導致哈希碼計算崩潰的壞種子。 我不這么認為。 即使是0
種子也能奏效。
Roslyn源代碼可以在AnonymousTypeGetHashCodeMethodSymbol
找到。 初始哈希碼值基於匿名類型名稱的哈希值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.