【问题标题】:Overriding GetHashCode() C# Complex way or simple way? [closed]覆盖 GetHashCode() C# 复杂方式还是简单方式? [关闭]
【发布时间】:2016-02-11 03:48:41
【问题描述】:

我阅读的越多,我对博客、MSDN 以及其他 stackoverflow 问题和响应的困惑就越多。

本文:https://msdn.microsoft.com/en-us/library/ms173147%28VS.90%29.aspx 状态: "Equals 的新实现不应该抛出异常。建议任何覆盖 Equals 的类也覆盖 Object.GetHashCode"

但是这篇文章:http://www.aaronstannard.com/overriding-equality-in-dotnet/ 状态: “一个重要的警告 - 只有在你的对象不可变时才应该覆盖 GetHashCode。

1) 那么,我会直接听微软的第一篇文章吗?还是我听第二篇文章似乎比微软有更强的哈希码返回。

2) 如果使用 Microsoft 示例,该示例使用异或返回实例成员 int 值。这是我对所有值类型都做的事情吗?那么 int32 结构上为什么有一个返回哈希码的选项呢?我什么时候返回哈希码和值?

3) 我什么时候使用更复杂的哈希码返回(来自第二篇文章)与更简单的第一篇(微软)文章

4) 如果对象是不可变的且不能更改,并且相同类型的两个不可变对象的值相等,那么 HashCode 为何重要?

【问题讨论】:

  • 一篇帖子有很多问题(如果不是全部的话,大多数问题已经在 SO 上讨论死了)。一些你可以考虑的问题 - stackoverflow.com/questions/873654/…, stackoverflow.com/questions/462451/…
  • 我已经回答了你帖子的第一部分。每个帖子只问一个问题。
  • 您的问题 4 相当于“为什么哈希码永远很重要?”。为此,您需要了解哈希表的工作原理(维基百科)。

标签: c# .net


【解决方案1】:

1) 两篇文章都是正确的。他们并不矛盾。如果您在可变对象中覆盖 GetHashCode(),您可能会例如把它放在一个HashSet中,改变对象的属性从而改变哈希码,然后在HashSet中找不到它。

2) XOR 是组合多个整数值的弱方法。如需更好的方法,请参阅Combining Java hashcodes into a "master" hashcode

3) 您需要确保您返回的哈希码能够最大限度地减少表示不同值的对象之间的哈希冲突。您需要更好地描述您的域以获得好的答案。

4) 哈希码用于字典和哈希集之类的东西。如果您有 Dictionary<MyType, int>,您希望避免 MyType 的两个实例散列到相同的值,因此如果它们实际上不相等,则被视为相同的键。

【讨论】:

  • 谢谢埃里克。您在 #1 中提出了一个很好的观点,Microsoft 文档没有涉及到这一点。
  • 已经有大量关于 SO 的深入讨论。查看此页面右侧的链接和相关内容,以更深入地了解该主题。
  • @user1794106:来自object.GetHashCode 文档:“如果您确实选择为可变引用类型覆盖 GetHashCode,您的文档应该清楚说明您的类型的用户不应修改对象值,而对象存储在哈希表中。”
【解决方案2】:

在我看来,如果你覆盖 Equals,你应该总是覆盖 GetHashCode - 否则你就违反了这些方法的约定。

但是,对于可变类型,客户端代码需要注意,如果它确实改变了用作 Dictionary 中的键或 HashSet 中的条目的值,在某种程度上影响平等(因此可能影响哈希码),他们很可能最终无法再次找到它。这在 Dictionary<,> 文档中指定,例如:

只要将对象用作Dictionary<TKey, TValue> 中的键,它就不能以任何影响其哈希值的方式发生变化。

基本上,正确使用类型取决于客户端 - 就像处理 IDisposable 实例取决于客户端一样,不要使用并非设计为在没有同步的多个线程中实现线程安全的类型等等

【讨论】:

  • it's up to the client to use the type properly 我想知道世界范围内有多少错误是由于类设计不遵循常见/常规约定。
  • @EricJ.: 当然,有些人会滥用它——但我宁愿它那样做,而不是那些会使用 正确 类型的人(使用 in 后不会发生变异)字典)但不能,因为该类型决定通过违反书面合同来“安全行事”。
猜你喜欢
  • 1970-01-01
  • 2014-05-23
  • 2011-05-13
  • 2012-03-08
  • 2013-03-16
  • 2012-07-13
  • 1970-01-01
  • 1970-01-01
  • 2021-09-30
相关资源
最近更新 更多