Hashcodes是一样的,但是!=返回true?

时间:2012-09-21 20:14:38

标签: c# c#-4.0

我被一个看似简单的问题困扰了。我有两个对象,我正在与!=。

进行比较

当我运行应用程序时,a!= b为真。 当我设置断点并执行Watch时,a.GetHashCode()== b.GetHashCode()为真。

这两个(引用类型)对象是在不同的程序集中定义的,但我找不到对!=方法的覆盖(尽管覆盖了GetHashCode)。还有另一种解释吗?两个对象的GetHashCode可能是相同的,但是not-overriden!=会返回true吗?

感谢。

2 个答案:

答案 0 :(得分:6)

当两个不同的对象返回相同的代码时,它被称为“碰撞”。只有大约40亿个可能的整数值,以及[你的类名在这里]超过40亿个可能的值,一些碰撞是不可避免的。这就是基于散列的结构(即Dictionary)不能完全依赖GetHashCode的原因,它还需要一个合理的Equals实现才能生效。 Equals方法用于解决这些冲突。

当然,类的创建者也可能覆盖GetHashCodeEquals,并以某种方式犯了一个错误,在某种程度上违反了生成哈希码的“契约”。 Here是创建GetHashCode方法时要记住的一系列指南。请记住,您要做的事情相当少,另外还有一些事情可以让它有效地

return 0;实际上是一个完全可以接受的GetHashCode实现。它符合所有规则,它只有100%的机会导致冲突,所以它会非常低效,你不应该真的这样做。

答案 1 :(得分:1)

两个不等于具有相同哈希码的对象是完全合法的,但它对于两个等于具有不同哈希码的对象无效。

Dictionary样式集合类使用hashcode值(从指定为键的对象返回的GetHashCode值)将键/值对放入hashbin中。键的哈希码值相同的所有键/值对进入相同的哈希值。如果哈希码生成有效,则意味着字典中每个非空哈希宾中的键/值对很少(希望只有一个)。

当您通过将对象指定为键来访问字典中的内容时,用于查找要返回的正确值的伪逻辑是:

  1. 获取在请求中指定为键的对象的哈希码值(GetHashCode())
  2. 如果该哈希码存在非空哈希表,则迭代该哈希表中所有键/值对的键对象。对于hashbin中的每个键/值对,检查键对象Equals()是否作为请求的键传入的对象。如果是,则返回该键/值对中的Value对象。
  3. 与在List样式集合中查找对象(当哈希码分布良好时)相比,这使得字典查找非常有效。