重写GetHashCode()C#复杂方式还是简单方法?

时间:2016-02-10 19:35:27

标签: c# .net

我读的越多,我就越感到困惑,从博客,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)那么,我是否直接听微软的第一篇文章?或者我是否听第二篇文章似乎比Microsoft更强大的哈希码返回。

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

3)我何时使用更复杂的哈希码返回(来自第二篇文章)与第一篇(Microsoft)文章中的更简单

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

2 个答案:

答案 0 :(得分:4)

1)两篇文章都是正确的。它们并不矛盾。如果在可变对象中覆盖GetHashCode(),则可能是将它放在HashSet中,更改对象的属性,从而更改哈希代码,然后无法在HashSet中找到它。

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

3)您需要确保返回的哈希代码将最小化表示不同值的对象之间的哈希冲突。您需要更好地描述您的域名以获得良好的答案。

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

答案 1 :(得分:4)

我认为,如果您覆盖GetHashCode,则总是覆盖Equals - 否则您违反了这些方法的合同。

但是,对于可变类型,客户端代码需要知道,如果 突变用作Dictionary中的键或HashSet中的条目的值,以一种影响相等的方式(因此可能是哈希码),它们最终可能无法再次找到它。这在Dictionary<,>文档中指定,例如:

  

只要一个对象被用作Dictionary<TKey, TValue>中的一个键,就不能以任何影响其哈希值的方式进行更改。

基本上,由客户端正确使用类型 - 正如客户端要处理IDisposable实例一样,不要使用不是多线程设计为线程安全的类型没有同步等。