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

C# 要确保GetHashCode()方法为对象返回唯一值,我应该遵循哪些规则?,c#,.net,gethashcode,C#,.net,Gethashcode,要确保GetHashCode()方法为对象返回唯一值,我应该遵循哪些规则 例如: 我应该包括一些私人成员来计算吗 我应该乘而不是求和吗 我可以确定我正在为特定的对象图生成uniqe哈希代码吗?等等 您甚至不应该期望GetHashCode()为每个对象返回唯一的值。这不是GetHashCode()的重点 埃里克·利珀特有一本书,你应该仔细阅读。基本上,您希望得到的结果是,对于两个相等的对象,总是返回相同的值(并且您需要了解您所说的相等是什么意思),对于两个不相等的对象,可能返回不同的值 我个人倾

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

例如:

  • 我应该包括一些私人成员来计算吗
  • 我应该乘而不是求和吗
  • 我可以确定我正在为特定的对象图生成uniqe哈希代码吗?等等
您甚至不应该期望
GetHashCode()
为每个对象返回唯一的值。这不是
GetHashCode()
的重点

埃里克·利珀特有一本书,你应该仔细阅读。基本上,您希望得到的结果是,对于两个相等的对象,总是返回相同的值(并且您需要了解您所说的相等是什么意思),对于两个不相等的对象,可能返回不同的值

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

public override int GetHashCode()
{
    int hash = 17;
    hash = hash * 31 + field1.GetHashCode();
    hash = hash * 31 + field2.GetHashCode();
    hash = hash * 31 + field3.GetHashCode();
    ...
    return hash;
}
注意事项:

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

    hash = hash * 31 + (field2 == null ? 0 : field2.GetHashCode());
    

我想你的答案就在这里:见Jon Skeet答案,这是一种非常可靠的计算方法。时间证明:)


您不一定需要傻瓜式哈希代码,因为您还需要重写Equals进行比较。通常,我所做的是将我知道的不同对象的值连接成一个字符串,并返回该字符串的哈希值。

我将明确阅读这篇文章;但就我看来,这个想法是用素数来填充逻辑。也许这是一个非常愚蠢的问题,但你知道有没有办法计算出这种情况下最安全的素数?谢谢@铅笔蛋糕:最安全?对什么最安全?如果两个对象创建相同的散列码,那么一切都会正常工作——只需要稍微长一点的时间来区分键;看来我和你的看法不一样。谢谢你,乔恩@铅笔蛋糕:如果你担心攻击者利用你的哈希代码中的弱点,那么没有素数是正确的素数。在这种情况下,您需要做的是设计一个散列算法,该算法更改其自身的参数,从而使攻击者无法创建导致多次冲突的数据集。这只适用于高级玩家;如果你真的面临这种情况,那么请一位专业人士来处理这种情况,并知道如何正确处理。@Eric Lipert:顺便说一下,Jon提到的你的文章对我真的很有用!谢谢你!停止有多少个
String
实例?有多少个
int
实例?
String.GetHashCode
的返回类型是什么?你看到问题了吗?基于你之前的问题,你应该让GetHashCode()等人单独处理。首先问一下什么时候该处理它。不要发帖了,这里已经有很多问题了。我一直很好奇这种形式的哈希生成与Jon在回答中提到的那种相比的性能特征。这取决于你是否需要测试它。我发现这是一个“简单”或简单的方法,如果您只需要一个通用的哈希函数,它可能会相对接近于唯一的。所以我倾向于使用一行类似(“+member_a+member_b+member_c).HashCode();我从来没有遇到过这样的问题,但这是一种快速而肮脏的方式:P