22

我阅读了有关 StackOverflow 的大多数问题GetHashCode。但我仍然不确定是否必须覆盖GetHashCode引用类型。我从另一个问题的某人的回答中得到以下内容:

Object.GetHashCode() 使用 System.Object 类中的内部字段来生成哈希值。创建的每个对象都被分配一个唯一的对象键,在创建时存储为整数。这些键从 1 开始,并在每次创建任何类型的新对象时递增。

如果在 .NET Framework 3.5 中仍然如此(有人可以确认吗?),那么我看到的引用类型的默认实现的唯一问题是哈希码的分布很差。

我将分解我的问题:

a)因此,GetHashCode如果在 a 中使用它,建议也覆盖它,Dictionary或者默认实现是否执行得很好?

b)我有引用类型,因为它们具有唯一标识它们的字段,所以很容易做到这一点,但是那些所有成员也是引用类型的引用类型呢?我应该在那里做什么?

4

2 回答 2

20

如果您覆盖 Object.Equals(),则只需要在引用类型上覆盖 GetHashCode()。

原因很简单——通常,2 个引用总是不同的(a.Equals(b)==false,除非它们是同一个对象)。在这种情况下,GetHashCode() 的默认实现将提供 2 个不同的哈希值,所以一切都很好。

但是,如果您覆盖 Equals(),则无法保证此行为。如果两个对象相等(根据 Equals()),您需要保证它们与 GetHashCode 具有相同的哈希码,因此您应该覆盖它。

于 2009-04-20T18:26:45.843 回答
0

我只是做了一个样本测试,我看不到它是如何从 1 开始并增加的。

for (int i = 0; i < 16; i++)
{
    object obj = new object();
    Console.Write(obj.GetHashCode() + " ");
}

这些结果:

45653674 41149443 39785641 45523402 35287174 44419000 52697953 22597652 
10261382 59109011 42659827 40644060 17043416 28756230 18961937 47980820

事实上,使用 Reflector,我只能看到:

internal static extern int InternalGetHashCode(object obj);

所以它究竟是如何发生的对我来说是一个谜(可能有一个模式,但我现在不打算深入挖掘——也许是某种“伪随机数”算法?)。CLR 团队的某个人可以回答这个问题。

至于其他问题,里德实际上击败了我:GetHashCodeEquals。为了以防万一, MSDN页面用更多血淋淋的细节对其进行了描述。

于 2009-04-20T18:36:15.667 回答