我永远不需要在哈希表中存储对象。原因有两个:
另一方面,Equals()操作是一种非常常用的功能。
因此我想知道在实现Equals函数(我经常需要)时是否有必要实现GetHashCode(我从不需要)?
答案 0 :(得分:13)
我的建议 - 如果您不想使用它,请覆盖它并throw new NotImplementedException();
,以便您可以看到您需要它。
答案 1 :(得分:5)
如果您认为实现严格的顺序谓词比散列函数更容易实现,我认为您错了 - 它需要处理大量边缘情况(空值,类层次结构)。和散列函数aren't that difficult,真的。
答案 2 :(得分:4)
AVL树比哈希表慢得多。如果您只处理几件物品,那么这不会是一个大问题。 Hashtables有O(1)插入,删除和搜索,但AVL树有O(log(n))操作。
我会继续覆盖GetHashCode
和Equals
,原因有两个。
另外,我不得不质疑BST的选择。 AVL树有点不合时宜。还有其他更现代的BST更容易实现和工作(有时更好)。如果您确实需要一个维护排序的数据结构,那么请考虑这些替代方案。
1 XOR策略存在一个微妙的关联性问题,在a^b = b^a
之后的某些情况下可能会导致冲突。来自Effective Java的解决方案已经实现了类似邪教的识别,这也很容易实现。
答案 3 :(得分:3)
如果您使用Dictionary
或SortedList
并覆盖Equals
,则需要使用哈希函数,否则它们会中断。 {B}中也会使用Equals
,如果其他人使用您的对象,他们会期望GetHashCode
能够合理地行事。
请注意,哈希函数不必那么复杂。基本版本是获取您用于相等的任何成员变量的哈希值,将每个成员变量与一个单独的互质数相乘,并将它们一起进行异或。
答案 4 :(得分:2)
您无需实施它。如果你编写自己的Equals()方法,我建议使用一些不破坏HashSet的GetHashCode实现。例如,您可以返回静态值(通常为42)。 HashSet性能会急剧下降,但至少它仍然可以工作 - 你永远不会知道将来谁会使用/编辑/维护你的代码。 (编辑:如果在散列结构中使用这样的类以便及早发现性能问题,则可能需要记录警告)
编辑:不要只使用XOR来合并属性的哈希码
其他人已经说过,您可以简单地组合所有属性的哈希码。而不是只使用XOR我会鼓励倍增结果。如果两个值相等(例如0xA ^ 0xA == 0x0
),则XOR可能导致0值。使用0xA * 0xA
,0xA * 31 + 0xA
或0xA ^ (0xA * 31)
可以轻松改善这种情况。
尽管如此,我的答案的意图是任何哈希函数都优于与equals不一致的哈希函数 - 即使它只返回一个静态值。只需选择用于相等性的任何属性子集(从none到all)并将结果放在一起。在选择哈希码的属性时,更喜欢那些组合非常独特的小子集(例如,名字,姓氏,生日 - 不需要添加整个地址)
答案 5 :(得分:1)
使用足够的哈希函数不很难。大多数情况下,对所有字段GetHashCode()
的结果进行简单的XOR就足够了。
答案 6 :(得分:1)
如果覆盖equals,则应覆盖MSDN中的GetHashCode():“建议任何覆盖Equals的类也覆盖System.Object.GetHashCode。” http://msdn.microsoft.com/en-us/library/ms173147.aspx
这两个函数应该匹配,如果两个对象相等,它们应该具有相同的散列值。这并不意味着如果两个对象具有相同的散列,则它们应该相等。您不需要过于复杂的哈希算法,但它应该尝试在整数空间内很好地分布。