自定义类型GetHashCode

可能重复:
覆盖System.Object.GetHashCode的最佳算法是什么?

我需要覆盖由三个字符串组成的类型的GetHashCode方法。 这是我的代码:

protected override int GetHashCode() { return str1.GetHashCode() + str2.GetHashCode() + str3.GetHashCode(); } 

这种方法实现的安全方法是什么?

最好的方法是避免在下列情况下产生相同哈希码的任何内容:

  • 交换了操作数的顺序
  • 具有大部分零值并且仅移动非零值

这些帐户上的添加(单独)和XOR都失败了。

这是一个更好的方法:

 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; } } 

无论你在代码中使用加法还是异或都有争议,我已经看到使用两者的例子,没有明确分析哪个是优越的(即均匀分布)。 选择一个并继续使用它。

397是ReSharper插件在生成GetHashCode实现时使用的默认值,并且显然是因为它通常溢出int的范围并因此更好地混合位而选择的。 围绕这种特定格式的GetHashCode实现有很多理论,但它是最常用的。

我总是使用独占或(Xor)而不是添加,因为它不具有在任何地方获取数字的倾向(比如朝向大值)。 所以我会说

 protected override int GetHashCode() { return str1.GetHashCode() ^ str2.GetHashCode() ^ str3.GetHashCode(); } 

是一个更好的实现。

你也可以试试它的变化,比如

 protected override int GetHashCode() { unchecked { return (str1.GetHashCode() * 1369) ^ (str2.GetHashCode() * 37) ^ str3.GetHashCode(); } } 

如果你想确保切换字符串的值会产生不同的结果。 有各种各样的方法可以用于散列(例如通用散列 ),所以只需要搜索散列方法,如果这就是你正在寻找的东西。