c# - 计算值类型和数组组合的哈希码
问题描述
似乎我无法理解 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 解决方案)?
解决方案
你使用HashCode.Combine
正确。问题是您StructuralEqualityComparer
用于相等比较而不是哈希码生成,因此两个字符串数组是“相等的”但默认情况下不会生成相同的哈希码。利用
public override int GetHashCode() => HashCode.Combine(I,
StructuralComparisons.StructuralEqualityComparer.GetHashCode(A));
这是必要的,因为Combine
将调用GetHashCode
每个实例,无论列表中的值如何,列表都会有所不同。因此,您需要指定如何生成哈希码。
推荐阅读
- android - android画中画不覆盖我的特殊视图
- c++ - 将 std::filesystem::path 与需要 UTF-8 char* 的库接口?
- javascript - Javascript - 重新排序和重新格式化日期
- javascript - 尝试将事件侦听器添加到添加到选择元素的节点,但是当我选择该选项时,没有任何反应
- r - 从列中的文件名列表中提取组件以在 R 中创建一个新列
- javascript - 获取所有可能的数组组合
- c++ - 纯数据结构的组合与继承
- javascript - 从 HTML 输入字段创建随机 javascript 数组
- java - 创建名称为“repositorySearchController”和可分页数据的 bean 时出错
- reactjs - 在 React Particles JS 中看不到图像