我是否需要在引用类型上覆盖GetHashCode()?

时间:2009-04-20 18:15:39

标签: c# .net dictionary gethashcode

我在StackOverflow上阅读了大多数关于GetHashCode的问题。但我仍然不确定是否必须覆盖引用类型GetHashCode。我从另一个问题的某些人那里得到了以下答案:

  

Object.GetHashCode()使用内部   System.Object类中的字段   生成哈希值。每个对象   created被赋予一个唯一的对象   密钥,存储为整数,如果是   创建。这些键从1开始   每次增加一个新对象时都会递增   任何类型都会被创建。

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

我会打破我的问题:

a)所以它建议覆盖GetHashCode,如果它在Dictionary中使用,或者默认实现是否正常?

b)我有很容易做的引用类型,因为它们有唯一标识它们的字段但是那些所有成员也是引用类型的引用类型呢。我该怎么办?

3 个答案:

答案 0 :(得分:16)

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

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

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

答案 1 :(得分: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);

所以真正发生的事情对我来说是个谜(可能有一种模式,但我不打算深入挖掘这一点 - 可能是某种“伪随机数”algorithm?)。来自CLR团队的人可以回答这个问题。

至于其他问题,Reed实际上打败了我:GetHashCodeEquals。 MSDN page用更多的血腥细节来描述它,以防万一。

答案 2 :(得分:0)

查看我在文章中留下的评论:GetHashCode Extension Method