Bel*_*lgi 15 c# object gethashcode
我正在阅读有效的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());
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
打印的前几个数字是:
37121646,
45592480,
57352375,
2637164,
41014879,
3888474,
25209742,
26966483,
31884011
Run Code Online (Sandbox Code Playgroud)
哪个似乎不合适
这些键从1开始,每次创建任何类型的新对象时都会递增...
Object.GetHashCode()
返回此值
然后,为了找到这个"内部字段System.Object
"我尝试使用ReSharper反编译源,但我找到的代码是
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
[__DynamicallyInvokable]
public virtual int GetHashCode()
{
return RuntimeHelpers.GetHashCode(this);
}
Run Code Online (Sandbox Code Playgroud)
再次使用反编译源我发现RuntimeHelpers.GetHashCode
实现为
[SecuritySafeCritical]
[__DynamicallyInvokable]
[MethodImpl(MethodImplOptions.InternalCall)]
public static int GetHashCode(object o);
Run Code Online (Sandbox Code Playgroud)
下面的MethodImpl属性似乎我无法查看执行,这对我来说是死路一条.
有人可以解释作者的评论(第一个引用)吗?
Object类中的内部字段是什么以及它如何用于实现Object.GetHashCode()
?
Han*_*ant 18
好的,我最好写一下.这本书非常不准确.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;
}
Run Code Online (Sandbox Code Playgroud)
之后,它存储在对象的所谓同步块中,以便后续调用返回相同的值.实际存储的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;
Run Code Online (Sandbox Code Playgroud)
有:
static DWORD dwHashCodeSeed = 123456789;
Run Code Online (Sandbox Code Playgroud)