字典<TKey,TValue>中的哈希码

Ram*_*esh 2 .net dictionary hashcode

我正在玩字典,偶然发现了下面的情景

public class MyObject
{
    public string I { get; set; }
    public string J { get; set; }
    public string K { get; set; }

    public override int GetHashCode()
    {
        int hashCode = (I+J+K).GetHashCode();
        Debugger.Log(9, "INFO", hashCode.ToString() + System.Environment.NewLine);
        return hashCode;
    }
}
class Program
{
    static void Main(string[] args)
    {
        MyObject obj1 = new MyObject() { I = "Hello", J = "World" };
        MyObject obj2 = new MyObject() { I = "Hello", J = "World" };

        Dictionary<MyObject, string> collection = new Dictionary<MyObject, string>();
        collection.Add(obj1, "1");
        var result = collection[obj2]; // KeyNotFound exception here.
    }
}
Run Code Online (Sandbox Code Playgroud)

我有MyObject类作为字典的键,我重写GetHashCode方法,根据存储在类中的值返回哈希码.

因此,当执行上面的代码时,obj1和obj2都返回相同的哈希码,但字典仍然会引发KeyNotFound异常.

有这种行为的原因是什么?

Ric*_*ook 7

在.NET中,GetHashCodeEquals方法一起使用以确定与集合中的存储有关的对象相等性.

请注意,哈希表比通过哈希码简单地将键映射到单个槽更复杂.由于哈希码的性质,冲突可能发生并且确实在实践中发生(尽管具有良好的哈希函数,这不应该经常发生).因此,大多数哈希表实现必须处理生成相同哈希码的两个不同对象的情况,并且这通常通过哈希表中的每个"时隙"处的链表来实现.哈希码用于确定槽,并且该Equals方法用于确定对象存储在链表中的位置(在哈希表的大多数"标准"实现中).

然而,一句警告:很少有充分的理由来覆盖内置的行为GetHashCode.我发现这个有趣的SO线程正在讨论GetHashCode,Equals这应该值得一读:为什么重写Equals方法时重写GetHashCode很重要?.它讨论了改变行为的优点/缺点,好的和坏的散列函数的属性,这两种方法所需的属性以及其他好处.