1

我被一个看似简单的问题难住了。我有两个要与 != 进行比较的对象。

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

这两个(引用类型)对象是在不同的程序集中定义的,但是我找不到对 != 方法的覆盖(尽管 GetHashCode 已被覆盖)。对此还有其他解释吗?两个对象的 GetHashCode 是否可能相同,但未覆盖的 != 会返回 true?

谢谢。

4

2 回答 2

6

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

当然,类的创建者也有可能覆盖GetHashCodeEquals在某种程度上犯了一个错误,在某种程度上违反了生成哈希码的“合同”。 以下GetHashCode是创建方法时要牢记的准则列表。请记住,您必须做的事情相当少,而另一组事情可以做以使其有效地工作。

return 0;实际上是一个完全可以接受的GetHashCode实现。它符合所有规则,它有 100% 的几率引起碰撞,所以它会非常低效,你不应该真的这样做。

于 2012-09-21T20:18:43.320 回答
1

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

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

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

  1. 获取指定为请求中键的对象的哈希码值 (GetHashCode())
  2. 如果该哈希码有一个非空的哈希箱,则迭代该哈希箱中所有键/值对的键对象。对于 hashbin 中的每个键/值对,检查键对象是否等于()作为请求键传入的对象。如果是,则返回该键/值对中的 Value 对象。

与在 List 样式集合中查找对象相比(当哈希码分布良好时),这就是字典查找非常有效的原因。

于 2012-09-21T21:02:24.110 回答