反复调用 HashCode.Combine

repeatedly calling HashCode.Combine

重复调用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;
}

我不确定像这样累积哈希码是否会产生唯一的哈希值? 如果不是,我该如何正确执行此操作?

Is it correct to repeatedly call HashCode.Combine ?

是的。这正是它的用途。

I am trying to create a general extension method to produce an object hashcode from combining the hashcodes of all its properties

这是一件奇怪的事情。您的哈希码是 per type,而不是 per object,因此您的方法接受一个对象很奇怪。为什么它不简单地接受一个类型?为什么基于其 属性 信息对象的散列来形成一个类型的散列是有用的?该哈希码没有特别有趣的特征,可以对其进行组合。

你能解释一下你想在这里做什么吗? 这段代码似乎很不对。不是因为你使用了combiner;因为你正在做它并且认为这会产生一些有用的东西。哈希码通常与相等性配对,但 属性 信息是引用相等性。这段代码对我来说毫无意义。

更新:发帖人相信检查 属性 信息 的 属性 会给你价值属性。这种信念是错误的。因此我的困惑。 (我不清楚这种信念是如何在代码测试中幸存下来的;也许原始发布者还没有运行这段代码。)

I am not sure if accumulating hashcodes like this will produce a unique hash ?

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

散列码的目的不是提供唯一值。如果您需要唯一值,请制作一个 GUID。如果您需要一个唯一的散列,请使用超过 32 位的加密强度散列。

多亏了所谓的"birthday paradox",你会很快发生碰撞。我在此处绘制了您的算法产生非唯一结果的概率:https://ericlippert.com/2010/03/22/socks-birthdays-and-hash-collisions/

同样,如果您认为哈希码是唯一的,那么听起来您的哈希码做错了

你能更详细地解释一下你在这里做什么吗?您的问题就是我们所说的 "XY" 问题。你有一些真正的问题,你有一个关于如何解决它的疯狂想法,现在你问一个关于这个疯狂想法的问题,它没有任何意义。问一个关于真正问题的问题;有更好的解决方法。

在这种情况下,我认为您应该使用 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();