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异常.
有这种行为的原因是什么?
在.NET中,GetHashCode与Equals方法一起使用以确定与集合中的存储有关的对象相等性.
请注意,哈希表比通过哈希码简单地将键映射到单个槽更复杂.由于哈希码的性质,冲突可能发生并且确实在实践中发生(尽管具有良好的哈希函数,这不应该经常发生).因此,大多数哈希表实现必须处理生成相同哈希码的两个不同对象的情况,并且这通常通过哈希表中的每个"时隙"处的链表来实现.哈希码用于确定槽,并且该Equals方法用于确定对象存储在链表中的位置(在哈希表的大多数"标准"实现中).
然而,一句警告:很少有充分的理由来覆盖内置的行为GetHashCode.我发现这个有趣的SO线程正在讨论GetHashCode,Equals这应该值得一读:为什么重写Equals方法时重写GetHashCode很重要?.它讨论了改变行为的优点/缺点,好的和坏的散列函数的属性,这两种方法所需的属性以及其他好处.