首页 > 解决方案 > 计算值类型和数组组合的哈希码

问题描述

似乎我无法理解 Hashcode 结构的文档:

我尝试了一个天真的:

public struct S : IEquatable<S>
{
    public int I { get; set;  }
    public string[] A { get; set;  }

    public override bool Equals(object? obj) => obj is S s && Equals(s);

    public bool Equals(S other) => I == other.I && StructuralComparisons.StructuralEqualityComparer.Equals(A, other.A);

    // public override int GetHashCode() => I.GetHashCode() ^ StructuralComparisons.StructuralEqualityComparer.GetHashCode(A);
    public override int GetHashCode() => HashCode.Combine(I, A);
}

这导致:

S s1 = new S() { I = 42, A = new string[] { "hello" } };
S s2 = new S() { I = 42, A = new string[] { "hello" } };
Assert.Equal(s1.GetHashCode(), s2.GetHashCode());

给出错误:

Xunit.Sdk.EqualException: 'Assert.Equal() Failure
Expected: 840823323
Actual:   -1160370390'

什么是正确的使用方法HashCode.Combine(我不喜欢我之前的 XOR 解决方案)?

标签: c#hashcode

解决方案


你使用HashCode.Combine正确。问题是您StructuralEqualityComparer用于相等比较而不是哈希码生成,因此两个字符串数组是“相等的”但默认情况下不会生成相同的哈希码。利用

public override int GetHashCode() => HashCode.Combine(I, 
       StructuralComparisons.StructuralEqualityComparer.GetHashCode(A));

这是必要的,因为Combine将调用GetHashCode每个实例,无论列表中的值如何,列表都会有所不同。因此,您需要指定如何生成哈希码。


推荐阅读