首页 > 解决方案 > GetHashCode 为不同的位标志枚举返回相同的值

问题描述

我有每个元素的按位表示的标志类型枚举,如下所示

[DataContract]
[Flags]
public enum TestProduct : long
{
    [EnumMember]
    A1 = 0x1,
    [EnumMember]
    A2 = 0x2,
    [EnumMember]
    A3 = 0x4,
    [EnumMember]
    A4 = 0x8,
    [EnumMember]
    A5 = 0x40,
    [EnumMember]
    A6 =0x4000000000,
}

我将其命名为 Flags Enum,因为我需要存储这些条目的组合。我在这里面临的问题是,我确实有一个通用代码来检查 HasCode,然后如果 HashCode 不为零,则执行一些操作。

在这种情况下,我为元素 A5 和 A6 返回相同的 Has 代码值,返回为 64(0x40 的二进制值)。

如果我有 A5 和 A6 的组合,它给我的哈希码为零。有人可以建议我如何处理这种情况以避免这种组合的值为零,为什么两者都给出与 A5 相同的哈希码。

下面的代码显示了它是如何表示的。

static void Main(string[] args)
{
    Console.Write("Hash Code for A5 is ");
    Console.WriteLine(Enums.TestProduct.A5.GetHashCode());
    Console.Write("Hash Code for A6 is ");
    Console.WriteLine(Enums.TestProduct.A6.GetHashCode());
    Console.Write("Hash Code for A6 | A5 is ");
    Console.WriteLine((Enums.TestProduct.A6 | Enums.TestProduct.A5).GetHashCode());
    Console.ReadLine();
}

结果如下: 在此处输入图像描述

标签: c#enumsgethashcodeenum-flags

解决方案


为枚举值返回它喜欢的任何值是完全有效的GetHashCode,只要它总是返回相同的值。

虽然它是定义的实现,但我怀疑你得到 64 forA6和 0 for的原因是因为类型A6 | A5的实现。由于需要返回一个(即 32 位),它必须做一些额外的处理来散列 a (即 64 位)。GetHashCodelongGetHashCodeintlong

如果您查看Long.GetHashCode的参考源实现,您会发现它是高 32 位与低 32 位的异或。对于A6哪个是0x4000000000这将是0x40 | 0x00哪个0x40(64)。

因为A6 | A5你最终会得到0x4000000040,当高 32 位与低 32 位异或时,0x40 | 0x40它会给你 0。


推荐阅读