好的,在您因为互联网上发布了数百个类似的问题而生气之前,我可以向您保证,我刚刚花了几个小时阅读了所有这些问题,但还没有找到我问题的答案。
背景:
基本上,我的一个大型应用程序遇到了这样一种情况,即属性Binding
上的某些 sListBox.SelectedItem
将停止工作,或者在对当前选定的项目进行编辑后程序会崩溃。我最初询问“已添加具有相同键的项目”从此处的代码问题中选择 ListBoxItem 的异常,但没有得到答案。
直到本周我才有时间解决这个问题,当时我有几天的时间来解决这个问题。现在长话短说,我找到了问题的原因。这是因为我的数据类型类已经覆盖了Equals
方法,因此也覆盖了方法GetHashCode
。
现在对于那些不知道这个问题的人,我发现你只能使用不可变字段/属性来实现该GetHashCode
方法。使用 Harvey Kwok 对Overriding GetHashCode()帖子的回答的摘录来解释这一点:
问题是 Dictionary 和 HashSet 集合使用 GetHashCode 将每个项目放入存储桶中。如果hashcode是根据一些可变字段计算出来的,而对象放入HashSet或Dictionary后,字段确实发生了变化,则无法再从HashSet或Dictionary中找到该对象。
所以实际问题是因为我在GetHashCode
而引起的。当用户在 UI 中更改这些属性值时,对象的相关哈希码值会更改,然后无法在其集合中找到项目。
问题:
所以,我的问题是处理需要GetHashCode
在没有不可变字段的类中实现方法的情况的最佳方法是什么?对不起,让我更具体一些,因为那个问题被问过了。
Overriding GetHashCode()帖子中的答案表明,在这些情况下,最好简单地返回一个常量值......有些人建议返回该值1
,而另一些人建议返回一个素数。就个人而言,我看不出这些建议之间有任何区别,因为我原以为它们中的任何一个都只会使用一个存储桶。
此外,Eric Lippert 博客中GetHashCode 的指南和规则文章有一个标题为指南的部分:哈希码的分布必须是“随机的”,这突出了使用导致没有使用足够存储桶的算法的缺陷。他警告说,算法会减少使用的存储桶数量,并在存储桶变得非常大时导致性能问题。当然,返回一个常量就属于这一类。
我有一个想法,为我的所有数据类型类(仅在 C# 中,而不是数据库中)添加一个额外的Guid
字段,专门用于并且仅在GetHashCode
方法中使用。所以我想在这个长长的介绍结束时,我的实际问题是哪个实现更好?总结一下:
概括:
在没有不可变字段的类中重写 Object.GetHashCode() 时,最好从GetHashCode
方法中返回一个常量,还是为每个类创建一个附加readonly
字段,仅在GetHashCode
方法中使用?如果我应该添加一个新字段,它应该是什么类型,然后我不应该将它包含在Equals
方法中?
虽然我很高兴收到任何人的回答,但我真的希望能收到对这个主题有深入了解的高级开发人员的回答。