为什么GetHashCode在Object类中?
为什么GetHashCode是Object类的一部分? 只有一小部分对象用作哈希表中的键。 当我们希望类的对象作为哈希表中的键时,必须实现一个单独的接口,这不是更好吗?
必须有一个原因,MS团队决定将此方法包含在Object类中,从而使其“无处不在”。
这是从Java,IMO复制的设计错误。
在我完美的世界里:
-
ToString
将重命名为ToDebugString
以适当地设置期望值 -
Equals
和GetHashCode
将消失 -
IEqualityComparer
会有一个ReferenceEqualityComparer
实现:此时等于此的部分很容易,但如果被覆盖则无法获得“原始”哈希码 - 对象不会有与之关联的
Monitor
:Monitor
将具有构造函数,而Enter
/Exit
等将是实例方法。
平等(因此散列)通常会导致inheritance层次结构中的问题 – 只要您始终可以指定要使用的比较类型(通过IEqualityComparer
),并且对象可以自己实现IEquatable
,如果需要,我不明白为什么它应该在Object
。 EqualityComparer
如果T
没有实现IEquatable
,则IEquatable
可以使用引用实现,否则将IEquatable
对象。 生活会很愉快。
呃,好吧。 虽然我在这,但arrays协方差是另一个平台错误。 如果你想在C#中出现语言错误,如果你愿意,我可以开始另一个小咆哮;)(它仍然是我最喜欢的语言,但有些事我希望以不同的方式完成。)
我在其他地方写过这篇博文 ,顺便说一下 。
只有一小部分对象用作哈希表中的键
我认为这不是一个真实的陈述。 许多类通常用作哈希表中的键 – 并且经常使用对象引用本身。 System.Object中存在GetHashCode的默认实现意味着任何对象都可以用作键,没有限制。
这似乎比强制对象上的自定义接口要好得多,只是为了能够对它们进行哈希处理。 您永远不知道何时需要使用对象作为散列集合中的键。
在使用HashSet
类的东西时尤其如此 – 在这种情况下,通常,对象引用用于跟踪和唯一性,而不一定用作“键”。 如果散列需要一个自定义接口,许多类将变得不那么有用。
它允许任何对象被“身份”用作密钥。 这在某些情况下是有益的,并且在没有情况下有害。 那么,为什么不呢?
- 所以任何东西都可以锁定。 (八九不离十)
- 这样,
HashTable
可以采用对象与实现IHashable
的对象。 - 推动简单的平等比较。
对于没有直接实现它的对象,它默认为.NET的内部哈希代码,我认为它是对象实例的唯一ID或它占用的内存占用的哈希。 (我不记得了,.NET Reflector无法超越该类的.NET组件)。
GetHashCode位于对象中,因此您可以将任何内容用作Hashtable(基本容器类)的键。 它提供对称性。 我可以把任何东西放到ArrayList中,为什么不是Hashtable?
如果您需要类来实现IHashable,那么对于每个未实现IHashable的密封类,当您想要将其用作包含散列function的密钥时,您将编写适配器。 相反,你默认得到它。
Hashcodes也是对象相等性比较的第二行(第一行是指针相等)。
如果每个类都有GetHashCode,您可以将每个对象放在哈希中。 想象一下,您有一个使用第三方对象(您无法修改)并希望将它们放入ab哈希。 如果这些对象没有实现你的虚构IHashable
你就做不到。 这显然是一件坏事;)
只是一个猜测,但垃圾收集器可能在内部存储一些对象的哈希表(可能是为了跟踪可终结的对象),这意味着任何对象都需要有一个哈希键。