[英]Implementation of Object.GetHashCode()
我正在閱讀Effective C#並且有一條關於Object.GetHashCode()
的評論,我不明白:
Object.GetHashCode()
使用System.Object
類中的內部字段來生成哈希值。 創建時,為每個創建的對象分配一個唯一的對象鍵,存儲為整數。
這些鍵從1開始,每次創建任何類型的新對象時都會遞增。 對象標識字段在System.Object
構造函數中設置,以后不能修改。Object.GetHashCode()
將此值作為給定對象的哈希碼返回。
我試着查看Object.GetHashCode()
的文檔,但沒有找到任何關於此的信息。
我編寫了一段簡單的代碼來打印新生成的對象的哈希碼:
using System;
namespace TestGetHashCode
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
object o = new object();
Console.WriteLine(o.GetHashCode());
}
}
}
}
打印的前幾個數字是:
37121646,
45592480,
57352375,
2637164,
41014879,
3888474,
25209742,
26966483,
31884011
哪個似乎不合適
這些鍵從1開始,每次創建任何類型的新對象時都會遞增...
Object.GetHashCode()
返回此值
然后,為了在System.Object
找到這個“內部字段”,我嘗試使用ReSharper反編譯源,但我找到的代碼是
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
[__DynamicallyInvokable]
public virtual int GetHashCode()
{
return RuntimeHelpers.GetHashCode(this);
}
再次使用反編譯源我發現RuntimeHelpers.GetHashCode
實現為
[SecuritySafeCritical]
[__DynamicallyInvokable]
[MethodImpl(MethodImplOptions.InternalCall)]
public static int GetHashCode(object o);
在MethodImpl屬性之后 ,似乎我無法查看實現,這對我來說是一個死胡同。
有人可以解釋作者的評論(第一個引用)嗎?
Object類中的內部字段是什么以及如何使用它來實現Object.GetHashCode()
?
好的,我最好寫一下。 這本書非常不准確。 Object.GetHashCode()的值在CLR內部生成,並且只要第一次調用GetHashCode(),就會按需計算。 我將引用SSCLI20發行版中的代碼,clr / src / vm / thread.h具有生成數字的函數,它看起來像這樣(為了便於閱讀而編輯):
inline DWORD GetNewHashCode()
{
// Every thread has its own generator for hash codes so that we won't get into a
// situation where two threads consistently give out the same hash codes.
// Choice of multiplier guarantees period of 2**32
// see Knuth Vol 2 p16 (3.2.1.2 Theorem A).
DWORD multiplier = m_ThreadId*4 + 5;
m_dwHashCodeSeed = m_dwHashCodeSeed*multiplier + 1;
return m_dwHashCodeSeed;
}
之后,它存儲在對象的所謂同步塊中,以便后續調用返回相同的值。 實際存儲的32位中只有26位,同步塊需要一些狀態位空間。 仍然足以產生非常高質量的哈希碼,碰撞是非常罕見的。
該代碼中m_ThreadId變量的存在可以使用解釋。 為每個單獨的線程存儲隨機數生成器種子。 避免不得不鎖定的訣竅。
m_dwHashCodeSeed在Thread構造函數中初始化,如下所示:
// Initialize this variable to a very different start value for each thread
// Using linear congruential generator from Knuth Vol. 2, p. 102, line 24
dwHashCodeSeed = dwHashCodeSeed * 1566083941 + 1;
m_dwHashCodeSeed = dwHashCodeSeed;
有:
static DWORD dwHashCodeSeed = 123456789;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.