为什么GetHashCode在Object类中?

时间:2010-06-22 18:31:48

标签: c# .net language-agnostic clr

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

MS团队决定将此方法包含在Object类中,从而使其“随处可用”。

7 个答案:

答案 0 :(得分:17)

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

在我完美的世界里:

  • ToString将重命名为ToDebugString以正确设置期望
  • EqualsGetHashCode将会消失
  • ReferenceEqualityComparer会有一个IEqualityComparer<T>实现:此时平等的部分很容易,但如果被覆盖则无法获得“原始”哈希码
  • 对象没有与之关联的监视器:Monitor将具有构造函数,Enter / Exit等将是实例方法。

Equality(以及哈希)通常会导致继承层次结构中出现问题 - 只要您始终可以指定要使用的比较类型(通过IEqualityComparer<T>),对象就可以自己实现IEquatable<T>如果他们愿意,我不明白为什么它应该在Object。如果EqualityComparer<T>.Default未实现T,则IEquatable<T>可以使用参考实现,否则将遵从这些对象。生活会很愉快。

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

我在其他地方blogged about this,顺便说一下。

答案 1 :(得分:3)

  

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

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

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

  1. 所以任何东西都可以锁上。 (八九不离十)
  2. 那样HashTable可以将对象与实现IHashable的对象进行对比。
  3. 推动简单的平等比较。
  4. 在没有直接实现它的对象上,它默认为.NET的内部哈希代码,我认为它是对象实例的唯一ID或它占用的内存占用的哈希值。 (我不记得了,.NET Reflector无法超越该类的.NET组件。)

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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