【发布时间】:2011-07-31 16:49:26
【问题描述】:
我一直在思考这个问题:Object.GetHashCode 在 CLR 或 Java 中究竟是如何实现的?这个方法的约定是,如果在同一个对象实例上调用它,它应该总是返回相同的值。
请注意,我说的是 GetHashCode() 的默认实现。派生类不需要重写此方法。如果他们选择不这样做,他们本质上将具有引用语义:在哈希表 &c 中使用时,默认情况下相等等于“指针相等”。这意味着不知何故,运行时必须在对象的整个生命周期内为对象提供一个恒定的哈希码。
如果我运行的机器是 32 位的,并且对象实例从未在内存中移动,理论上可以返回对象的地址,重新解释为 Int32。这很好,因为所有不同的对象都有不同的地址,因此会有不同的哈希码。
但是,这种方法存在缺陷,其中包括:
-
1234563 /li>
在 64 位系统上,对象的地址太宽,无法放入 Int32。
因为托管对象倾向于与 2 的某个偶数幂对齐,所以最底部的位将始终为零。当哈希码用于索引哈希表时,这可能会导致错误的分布模式。
在 .NET 中,System.Object 由一个同步块和一个类型句柄组成,仅此而已,因此哈希码不能缓存在实例本身中。不知何故,运行时能够提供持久的哈希码。如何? Java、Mono 和其他运行时如何做到这一点?
【问题讨论】: