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

哈希碰撞定义解析及C# Dictionary链式存储失效问题咨询

哈希碰撞的定义与代码问题解析

一、哈希碰撞到底是什么?

  • 哈希碰撞的核心定义是:两个不同的对象生成了完全相同的哈希码,这是哈希碰撞的本质。
  • 至于“进入Dictionary的同一个桶”,这是哈希碰撞带来的结果——因为Dictionary会根据哈希码计算桶的索引,相同哈希码必然会被分配到同一个桶里。反过来,就算两个对象哈希码不同,也可能因为索引计算(比如取模)的巧合落到同一个桶,这种属于广义上的桶冲突,但通常我们说的哈希碰撞特指哈希码重复的情况。

二、你的C#代码为什么没触发链式存储?

先看你的代码逻辑:

static Dictionary<Number, string> dict = new Dictionary<Number, string>();

class Number
{
    private int X;

    public Number(int x)
    {
        X = x;
    }

    public override bool Equals(object obj)
    {
        Number other = obj as Number;
        return X.Equals(other.X);
    }

    public override int GetHashCode()
    {
        return X;
    }
}

public static void Main(string[] args)
{
    dict.Add(new Number(5), "Value5");
    dict.Add(new Number(2), "Value2");
    dict.Add(new Number(5), "Value52"); // 这里会直接报错
}

问题出在:你添加的两个new Number(5)对象,在Dictionary看来是同一个键——因为它们的Equals方法返回true,且哈希码相同。Dictionary不允许重复键,所以执行第三行Add的时候会直接抛出ArgumentException,根本到不了链式存储那一步。

链式存储是用来处理键不同但哈希码相同的情况。比如修改GetHashCode方法,让不同X值返回相同哈希码:

public override int GetHashCode()
{
    return X % 2; // 所有奇数返回1,偶数返回0
}

这时候添加new Number(1)和new Number(3),它们是不同的键(Equals返回false)但哈希码相同,Dictionary才会把这两个元素放到同一个桶里,用链式存储保存,不会报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 02:32:25