Custom type GetHashCode
本问题已经有最佳答案,请猛点这里访问。
Possible Duplicate:
What is the best algorithm for an overridden System.Object.GetHashCode?
我需要为包含三个字符串的类型重写GetHashCode方法。这是我的代码:
1 2 3 4 | protected override int GetHashCode() { return str1.GetHashCode() + str2.GetHashCode() + str3.GetHashCode(); } |
这种方法实现的安全方法是什么?
最好的方法是避免产生相同哈希代码的任何事情,如果您:
- 交换了操作数的顺序
- 有一个很大的零值,只需移动非零值
添加(本身)和XOR在这些帐户上都失败。
下面是一个更好的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public override int GetHashCode() { unchecked { int result = 37; // prime result *= 397; // also prime (see note) if (str1 != null) result += str1.GetHashCode(); result *= 397; if (str2 != null) result += str2.GetHashCode(); result *= 397; if (str2 != null) result += str2.GetHashCode(); return result; } } |
无论您在代码中使用addition还是xor,都有待讨论,我已经看到了使用这两种方法的示例,但没有对哪一种方法进行明确的分析(即统一分布)。选择一个,然后跟着它走。
397是resharper加载项在生成gethashcode实现时使用的默认值,显然是选中的,因为它通常会溢出int的范围,从而更好地混合位。关于gethashcode实现的这种特定格式有很多理论,但它是最常用的一种。
我总是使用exclusive或(xor)而不是addition,因为它不倾向于在任何地方获取数字(比如大值)。所以我会这么说
1 2 | protected override int GetHashCode() { return str1.GetHashCode() ^ str2.GetHashCode() ^ str3.GetHashCode(); } |
是更好的实现。
你也可以尝试对它做一些改变,比如
1 2 3 4 5 6 7 8 | protected override int GetHashCode() { unchecked { return (str1.GetHashCode() * 1369) ^ (str2.GetHashCode() * 37) ^ str3.GetHashCode(); } } |
如果要确保切换字符串的值会产生不同的结果。有各种各样的方法可以用来散列(例如通用散列),所以只要搜索散列方法,如果这就是你要找的。