反复调用 HashCode.Combine

kof*_*fus 2 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;
}
Run Code Online (Sandbox Code Playgroud)

我不确定像这样累积哈希码是否会产生唯一的哈希值?如果不是,我怎么能正确地做到这一点?

Eri*_*ert 5

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

是的。这正是它的用途。

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

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

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

UPDATE:楼主是相信检查的属性信息的属性让你的财产的价值。这种信念是错误的。因此我的困惑。(我不清楚这种信念是如何在代码测试中幸存下来的;也许原始发布者尚未运行此代码。)

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

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

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

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

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

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


Din*_*rdo 5

在这种情况下,我相信你应该使用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();
Run Code Online (Sandbox Code Playgroud)