繁体   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