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

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

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

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

我会打破我的问题:

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

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

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

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

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

我刚刚做了一个样本测试,我没看到它是如何从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 页面用更多的血腥细节描述它,以防万一。

看看我在文章中留下的评论: GetHashCode扩展方法