簡體   English   中英

Object.GetHashCode()的實現

[英]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.

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