gpt4 book ai didi

c# - Object.GetHashCode() 的实现

转载 作者:可可西里 更新时间:2023-11-01 07:45:22 28 4
gpt4 key购买 nike

我正在阅读 Effective C#还有一条关于 Object.GetHashCode() 的评论我不明白:

Object.GetHashCode() uses an internal field in the System.Object class to generate the hash value. Each object created is assigned a unique object key, stored as an integer, when it is created.
These keys start at 1 and increment every time a new object of any type gets created. The object identity field is set in the System.Object constructor and cannot be modified later. Object.GetHashCode() returns this value as the hash code for a given object.

我试图查看 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

这似乎不符合那个

These keys start at 1 and increment every time a new object of any type gets created...Object.GetHashCode() returns this value

然后,为了找到这个“System.Object 中的内部字段”,我尝试使用 ReSharper decompiled sources但我找到的代码是

[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);

正在关注 the MethodImpl attribute看来我无法查看实现,这对我来说是死胡同。

有人可以解释一下作者的评论(第一句话)吗?

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;
}

之后它被存储在对象的所谓同步块(synchronized block)中,因此后续调用返回相同的值。生成的 32 位中只有 26 位实际被存储,同步块(synchronized block)需要一些状态位的空间。仍然足以生成非常高质量的哈希码,冲突非常罕见。

该代码中 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;

关于c# - Object.GetHashCode() 的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27195751/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com