好的,在您发疯之前,因为在互联网上发布了数百个类似的发音问题,我可以向您保证,我刚刚花了最后几个小时阅读了所有这些内容,但仍未找到我的问题的答案。
背景:
基本上,我的一个大型应用程序遇到了这样一种情况,即Binding属性上的某些ListBox.SelectedItem会停止工作,或者在对当前选定的项目进行编辑后,程序会崩溃。我最初在这里问'An item with the same key has already been added' Exception on selecting a ListBoxItem from code问题,但没有得到答案。
直到这个星期我才有时间解决这个问题,当时我有几天的时间来解决这个问题。现在简而言之,我找出了问题的原因。这是因为我的数据类型类已覆盖了Equals方法,因此也覆盖了GetHashCode方法。
现在,对于那些不知道此问题的人,我发现您只能使用不可变的字段/属性来实现GetHashCode方法。使用郭浩(Harvey Kwok)对Overriding GetHashCode()帖子的回答的摘录来解释这一点:

因此,实际的问题是由于在GetHashCode方法中使用了可变属性而引起的。当用户在UI中更改这些属性值时,对象的关联哈希码值也发生了更改,因此在其集合中不再可以找到项目。
问题:
因此,我的问题是处理在没有不可变字段的类中需要实现GetHashCode方法的情况的最佳方法是什么?抱歉,让我更具体一点,因为之前已经有人问过这个问题。
Overriding GetHashCode()帖子中的答案表明,在这种情况下,最好简单地返回一个常数值...有些建议返回值1,而另一些则建议返回素数。就我个人而言,我看不出这些建议之间有什么区别,因为我本以为其中只有一个存储桶。
此外,埃里克·利珀特(Eric Lippert)的博客中Guidelines and rules for GetHashCode文章的标题为“准则”:散列码的分布必须是“随机的”,这突出了使用算法导致使用的存储桶不足的陷阱。他警告说,算法会减少使用的存储桶数量,并在存储桶变大时引起性能问题。当然,返回常量属于此类。
我有一个想法,将一个额外的Guid字段添加到我的所有数据类型类中(仅在C#中,而不是在数据库中),专门用于且仅在GetHashCode方法中使用。因此,我想在这篇长篇介绍的最​​后,我的实际问题是哪种实现更好?总结一下:
概括:
当在没有不可变字段的类中重写Object.GetHashCode()时,是更好地从GetHashCode方法返回一个常量,还是为每个类创建一个额外的readonly字段,仅在GetHashCode方法中使用?如果我应该添加一个新字段,那么它应该是什么类型,然后不应该将它包括在Equals方法中?
我很高兴收到任何人的答复,但我确实希望收到对这一主题有深入了解的高级开发人员的答复。

最佳答案

回到基础。您读了我的文章;再读一遍。与您的情况相关的两条铁定规则是:

  • 如果x等于y,则x的哈希码必须等于y的哈希码。等效地:如果x的哈希码不等于y的哈希码,则x和y必须不相等。
  • 当x在哈希表中时,x的哈希码必须保持稳定。

  • 这些是正确性的要求。如果您不能保证这两个简单的事情,那么您的程序将是不正确的。

    您提出了两种解决方案。

    您的第一个解决方案是您始终返回一个常数。这满足了这两个规则的要求,但是随后您将被简化为哈希表中的线性搜索。您不妨使用一个列表。

    您提出的另一种解决方案是以某种方式为每个对象生成一个哈希码,并将其存储在该对象中。如果相等的项具有相等的哈希码,那完全是合法的。如果这样做,则会受到限制,使得如果哈希码不同,则x等于y必须为false。这似乎使值(value)平等基本上变得不可能。因为如果想要引用相等,就不会首先覆盖Equals,所以这似乎是一个非常糟糕的主意,但是只要equals是一致的,这是合法的。

    我提出了第三种解决方案,即:永远不要将对象放在哈希表中,因为哈希表首先是错误的数据结构。哈希表的目的是快速回答以下问题:“给定值是否在这组不可变值中?”和,您没有一组不可变的值,所以不要使用哈希表。使用正确的工具完成工作。使用列表,轻松进行线性搜索。

    第四种解决方案是:在用于相等性的可变字段上进行哈希处理,在每次对其进行突变之前将其从所有哈希表中删除,然后再将其放回。这满足了两个要求:哈希码符合相等性,并且哈希表中的对象的哈希值是稳定的,而且您仍然可以快速查找。

    关于c# - 在没有不可变字段的类中重写Object.GetHashCode()时返回什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19710028/

    10-08 22:28
    查看更多