moduloObjectHashcode MDA

注意

本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。

moduloObjectHashcode 托管调试助手 (MDA) 更改 Object 类的行为,以便对 GetHashCode 方法返回的哈希代码执行取模运算。 此 MDA 的模数默认为 1,这将导致 GetHashCode 对所有对象都返回 0。

症状

在迁移到公共语言运行时 (CLR) 的新版本后,程序将不再正确执行:

  • 程序从 Hashtable 获得错误的对象。

  • Hashtable 中的枚举顺序发生了一项变化,导致程序中断。

  • 以前相等的两个对象不再相等。

  • 以前不相等的两个对象现在相等。

原因

由于在 Hashtable 中的键的类上,Equals 方法实现通过比较 GetHashCode 方法调用的结果测试对象是否相等,因此程序可能从 Hashtable 中得到错误的对象。 不应该使用哈希代码测试对象是否相等,因为即使两个对象各自的字段具有不同的值,它们也可能具有相同的哈希代码。 虽然在实践中很罕见,但的确可能会发生这些哈希代码冲突。 这对 Hashtable 查找的影响是两个不相等的键似乎相等,并从 Hashtable 返回错误的对象。 出于性能的考虑,GetHashCode 的实现在运行时的两个版本之间可能改变,因此在一个版本中可能不会出现的冲突可能会在随后的版本中出现。 启用此 MDA 测试代码在哈希代码冲突时是否有 bug。 启用后,此 MDA 将导致 GetHashCode 方法返回 0,造成所有哈希代码冲突。 启用此 MDA 对程序的唯一影响是程序将会运行得更慢。

如果用于计算键的哈希代码的算法改变,则 Hashtable 中的枚举顺序可能随运行时版本而改变。 要测试程序是否依赖键的枚举顺序或哈希表的值,可启用此 MDA。

解决方法

从不使用哈希代码替换对象标识。 实现 Object.Equals 方法的重写,以便不比较哈希代码。

不要创建依赖哈希表中的键或值的枚举顺序的依赖项。

对运行时的影响

启用了此 MDA 时,应用程序的运行速度更慢。 此 MDA 只取得原本应该返回的哈希代码,改为返回除以某个模数之后得到的余数。

输出

此 MDA 没有输出。

Configuration

modulus 属性指定用于哈希代码的模数。 默认值为 1。

<mdaConfig>
  <assistants>
    <moduloObjectHashcode modulus="1" />
  </assistants>
</mdaConfig>

请参阅