You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何从byte数组转换的bool HashSet未去重,仍保留3个元素?

问题:为何从byte数组构造HashSet时会保留重复值?

我大致了解相关情况,但需要具体的原理解释:当我使用源自byte数组的数据构造HashSet时,为何它会保留重复值?我尝试调试,但得到bool数组后,所有元素看起来都是标准的bool类型。相关代码如下:

byte[] bytes = new byte[] { 0, 1, 2 };
ReadOnlySpan<byte> span = new(bytes);
ReadOnlySpan<bool> boolSpan = MemoryMarshal.Cast<byte, bool>(span);
bool[] bools = boolSpan.ToArray();

Console.WriteLine(string.Join(", ", bools)); // 输出:False, True, True

Console.WriteLine(new HashSet<bool>(bools).Count); // 输出:3??
Console.WriteLine(string.Join(", ", new HashSet<bool>(bools))); // 输出:False, True, True

原理分析

核心原因在于非规范的bool实例与HashSet的判断逻辑冲突:

  1. bool的底层存储规范与强制转换的特殊性
    .NET中bool类型的官方规范是:false对应字节0x00,true对应字节0x01。但通过MemoryMarshal.Cast<byte, bool>直接操作内存的方式,可以创建出底层字节为非0非1的bool实例(比如示例中byte=2转成的bool,底层是0x02)。

  2. ToString的逻辑判断
    当调用bool.ToString()时,逻辑是"非0即True",所以不管底层是0x01还是0x02,都会输出True,这就造成了视觉上的"重复值",但它们的底层存储并不相同。

  3. HashSet的元素重复判断逻辑
    HashSet判断元素是否重复时,会先比较哈希码(GetHashCode()),只有哈希码相同才会进一步调用Equals()验证:

    • 对于bool的Equals()方法:是逻辑相等判断,只要两个bool的底层值都是非0(或都是0),就会返回true。
    • 但bool的GetHashCode()方法:在.NET的多数实现中,是直接基于底层字节值计算哈希码,而非统一返回1表示true。

    这就导致了矛盾:示例中两个"视觉上的True",底层分别是0x01和0x02,它们的哈希码分别为1和2——HashSet看到哈希码不同,就直接判定为不同元素,不会再调用Equals(),所以这两个"True"会被同时保留在HashSet中。


内容的提问来源于stack exchange,提问作者Drago Rosson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:42:30