我使用一些包含1-2个int的标识类/结构,也可以是日期时间或小字符串。我将它们用作字典中的键。
对于像这样的东西,GetHashCode的优秀覆盖是什么?有些东西很简单,但仍然有点高效。
由于
答案 0 :(得分:1)
查看Essential C#。
它包含有关如何正确覆盖GetHashCode()
的详细说明。
哈希码的目的是通过生成与对象值对应的数字来有效地平衡哈希表。
- 必需:等于对象必须具有相同的哈希码(如果
a.Equals(b)
,则为a.GetHashCode() == b.GetHashCode()
)- 必需:
GetHashCode()
在特定对象的生命周期内返回应该是常量(相同的值),即使对象的数据发生了变化。在许多情况下,您应该缓存方法返回以强制执行此操作。- 必填:
GetHashCode()
不应抛出任何例外情况;GetHashCode()
必须始终成功返回值。- 性能:哈希代码应尽可能唯一。但是,由于哈希码只返回
int
,因此对于具有可能比int可以容纳的值更多的值的对象,哈希码必须重叠 - 几乎所有类型。 (一个明显的例子是long
,因为long
值可能比int
唯一标识的值更多。)- 性能:可能的哈希码值应均匀分布在
int
的范围内。例如,创建一个哈希,不考虑基于拉丁语的语言中字符串的分布主要以最初的128个ASCII字符为中心这一事实会导致字符串值的分布非常不均匀,并且不会很强{{1算法。- 性能:
GetHashCode()
应针对性能进行优化。如果哈希码不同,GetHashCode()
通常用于GetHashCode()
实现中以短路完全等于比较。因此,当类型在字典集合中用作键类型时,经常会调用它。- 性能:两个对象之间的细微差别会导致哈希码值之间存在很大差异 - 理想情况下,对象中的1位差异会导致哈希码的大约16位发生变化,平均。这有助于确保哈希表保持平衡,无论它如何“分解”哈希值。
- 安全性:攻击者应该很难制作具有特定哈希码的对象。攻击是使用大量数据填充散列表,这些数据都散列为相同的值。然后,哈希表实现变为O(n)而不是O(1),从而导致可能的拒绝服务攻击。
如前所述,您还要考虑一些有关覆盖Equals()
的要点,并且有一些代码示例显示了如何实现这两个函数。
所以这些信息应该给出一个起点,但我建议购买这本书并阅读完整的第9章(至少是前12个方面),以获得关于如何正确实现这两个关键功能的所有要点。
答案 1 :(得分:1)