为了确保GetHashCode()方法为对象返回唯一值,我应该遵循哪些规则?

pen*_*ake 0 .net c# gethashcode

为了确保GetHashCode()方法为对象返回唯一值,我应该遵循哪些规则?

例如:

  • 我应该包括一些prive成员进行计算吗?
  • 我应该乘以而不是总和吗?
  • 我可以确定我是否为特定对象图生成了一个uniqe哈希码?等等

Jon*_*eet 6

你甚至不应该瞄准GetHashCode()每个对象返回一个独特的价值.这不是GetHashCode().

Eric Lippert有一篇关于哈希码好文章,你应该仔细阅读.基本上你想要得到的东西总会为两个相等的对象返回相同的值(并且你需要通过相等来计算出你的意思)并且可能会为两个不相等的对象返回不同的值.

我个人倾向于使用这样的实现:

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 31 + field1.GetHashCode();
    hash = hash * 31 + field2.GetHashCode();
    hash = hash * 31 + field3.GetHashCode();
    ...
    return hash;
}
Run Code Online (Sandbox Code Playgroud)

需要注意的事项:

  • 如果你有可变对象,小心!在将对象用作哈希映射中的键之后,不应该对对象进行变异.
  • 如果您的字段可以为null,则需要在计算哈希值时检查该字段.例如:

    hash = hash * 31 + (field2 == null ? 0 : field2.GetHashCode());
    
    Run Code Online (Sandbox Code Playgroud)

  • @pencilCake:如果你担心攻击者利用你的哈希码中的弱点,那么没有素数就是*right*素数.在这种情况下,您需要做的是设计一种哈希算法,以一种攻击者无法制作导致许多冲突的数据集的方式更改其自身参数.这只适用于高级玩家; 如果这是您实际面临的情况,那么聘请一位处理此类情景的专业人员,并知道如何正确行事. (3认同)
  • @pencilCake:最安全吗?最安全的是什么?如果两个对象创建相同的哈希代码,那么一切都将仍然有效 - 它只需要*稍长*来区分键. (2认同)