反复调用HashCode.Combine

时间:2018-06-28 23:03:39

标签: c# .net-core c#-7.0 asp.net-core-2.1

重复调用HashCode.Combine是否正确?

我正在尝试创建一种通用的扩展方法,以通过组合其所有属性的哈希码来生成对象哈希码,如下所示:

using System;
public static int GetCombinedPropertiesHashCode(this object obj)
{
    int hash = obj.GetType().GetHashCode();
    foreach (var property in obj.GetType().GetProperties()) hash=HashCode.Combine(hash, property.GetHashCode());
    return hash;
}

我不确定是否像这样累积哈希码会产生唯一的哈希? 如果没有,我该怎么做呢?

2 个答案:

答案 0 :(得分:3)

  

重复调用HashCode.Combine是否正确?

是的。这正是它的目的。

  

我正在尝试创建一种通用扩展方法,通过结合其所有属性的哈希码来生成对象哈希码

这是一件奇怪的事情。您的哈希码是每个类型,而不是每个对象,因此奇怪的是,您的方法需要一个对象。为什么不简单地采用类型?又为什么基于其属性信息对象的哈希值形成类型的哈希值有用呢?该哈希码没有特别有趣的特征,可以使其组合起来很有用。

您能在这里解释您要做什么吗? 此代码似乎非常错误。并非由于您使用了组合器;因为您正在做所有事情,并认为这会产生有用的东西。哈希码通常与等号配对,但是属性信息引用相等。这段代码对我来说毫无意义。

更新:最初的发布者认为检查属性的财产信息会为您提供财产的价值。这种信念是错误的。因此,我感到困惑。 (对我来说,这种信念甚至在一次测试代码后如何存活下来还不清楚;也许最初的发布者尚未运行此代码。)

  

我不确定是否像这样累积哈希码会产生唯一的哈希?

绝对不会产生唯一的哈希。哈希码是32位整数;只有四十亿!可能有超过40亿种类型,因此绝对有至少两种类型会提供相同的哈希码。

哈希码的目的不是提供唯一值。如果需要唯一值,请创建一个GUID。如果您需要唯一的哈希,请使用长度超过32位的加密强度哈希。

多亏了所谓的“生日悖论”,您很快就会发生碰撞。我在这里绘制了您的算法产生非唯一结果的概率:https://ericlippert.com/2010/03/22/socks-birthdays-and-hash-collisions/

再次,如果您认为哈希码是唯一的,听起来好像您在对哈希码做错了什么

您能详细说明您在这里做什么吗?您的问题是我们所说的“ XY”问题。您有一个真正的问题,您对如何解决这个问题有一个疯狂的想法,现在您正在问一个关于疯狂的想法的问题,这没有任何意义。提出有关实际问题的问题;有更好的解决方法。

答案 1 :(得分:1)

在这种情况下,我认为您应该使用HashCode.Add。您可以改为在for循环中执行此操作。然后,您将在循环结束时仅生成一次HashCode,而不是在每个循环中都进行生成。对我来说,这似乎更有效率。

示例:

    var hash = new System.HashCode();

    foreach (var obj in myObjs)
    {
        hash.Add(obj.myStringProp, System.StringComparer.OrdinalIgnoreCase);
        hash.Add(obj.myLongProp);
        hash.Add(obj.myEnumProp);
    }

    return hash.ToHashCode();