为什么GetHashCode在Object类中?

为什么GetHashCode是Object类的一部分? 只有一小部分对象用作哈希表中的键。 当我们希望类的对象作为哈希表中的键时,必须实现一个单独的接口,这不是更好吗?

必须有一个原因,MS团队决定将此方法包含在Object类中,从而使其“无处不在”。

这是从Java,IMO复制的设计错误。

在我完美的世界里:

  • ToString将重命名为ToDebugString以适当地设置期望值
  • EqualsGetHashCode将消失
  • IEqualityComparer会有一个ReferenceEqualityComparer实现:此时等于此的部分很容易,但如果被覆盖则无法获得“原始”哈希码
  • 对象不会有与之关联的MonitorMonitor将具有构造函数,而Enter / Exit等将是实例方法。

平等(因此散列)通常会导致inheritance层次结构中的问题 – 只要您始终可以指定要使用的比较类型(通过IEqualityComparer ),并且对象可以自己实现IEquatable ,如果需要,我不明白为什么它应该在ObjectEqualityComparer.Default如果T没有实现IEquatable ,则IEquatable可以使用引用实现,否则将IEquatable对象。 生活会很愉快。

呃,好吧。 虽然我在这,但arrays协方差是另一个平台错误。 如果你想在C#中出现语言错误,如果你愿意,我可以开始另一个小咆哮;)(它仍然是我最喜欢的语言,但有些事我希望以不同的方式完成。)

我在其他地方写过这篇博文 ,顺便说一下 。

只有一小部分对象用作哈希表中的键

我认为这不是一个真实的陈述。 许多类通常用作哈希表中的键 – 并且经常使用对象引用本身。 System.Object中存在GetHashCode的默认实现意味着任何对象都可以用作键,没有限制。

这似乎比强制对象上的自定义接口要好得多,只是为了能够对它们进行哈希处理。 您永远不知道何时需要使用对象作为散列集合中的键。

在使用HashSet类的东西时尤其如此 – 在这种情况下,通常,对象引用用于跟踪和唯一性,而不一定用作“键”。 如果散列需要一个自定义接口,许多类将变得不那么有用。

它允许任何对象被“身份”用作密钥。 这在某些情况下是有益的,并且在没有情况下有害。 那么,为什么不呢?

  1. 所以任何东西都可以锁定。 (八九不离十)
  2. 这样, HashTable可以采用对象与实现IHashable的对象。
  3. 推动简单的平等比较。

对于没有直接实现它的对象,它默认为.NET的内部哈希代码,我认为它是对象实例的唯一ID或它占用的内存占用的哈希。 (我不记得了,.NET Reflector无法超越该类的.NET组件)。

GetHashCode位于对象中,因此您可以将任何内容用作Hashtable(基本容器类)的键。 它提供对称性。 我可以把任何东西放到ArrayList中,为什么不是Hashtable?

如果您需要类来实现IHashable,那么对于每个未实现IHashable的密封类,当您想要将其用作包含散列function的密钥时,您将编写适配器。 相反,你默认得到它。

Hashcodes也是对象相等性比较的第二行(第一行是指针相等)。

如果每个类都有GetHashCode,您可以将每个对象放在哈希中。 想象一下,您有一个使用第三方对象(您无法修改)并希望将它们放入ab哈希。 如果这些对象没有实现你的虚构IHashable你就做不到。 这显然是一件坏事;)

只是一个猜测,但垃圾收集器可能在内部存储一些对象的哈希表(可能是为了跟踪可终结的对象),这意味着任何对象都需要有一个哈希键。