【发布时间】:2009-10-13 18:05:58
【问题描述】:
只是在TKey 中覆盖Equals 并没有帮助。
public override bool Equals(object obj)
{ /* ... */ }
...Equals() 永远不会被调用...
【问题讨论】:
标签: c# .net dictionary
只是在TKey 中覆盖Equals 并没有帮助。
public override bool Equals(object obj)
{ /* ... */ }
...Equals() 永远不会被调用...
【问题讨论】:
标签: c# .net dictionary
当您进行字典查找时,事情发生的顺序是这样的:
如果桶永远不匹配(因为 GetHashCode 没有被覆盖),那么你永远不会调用 Equals。这就是为什么你应该始终实现这两个函数的部分原因 - 如果你想在散列集合中使用你的对象,你应该重写这两个函数(比调用 base.GetHashCode() 更有意义)。
如果您正在实现一个类,您应该实现一个 GetHashCode 例程,该例程为 Equal 的项目返回相同的哈希码。理想情况下,您希望尽可能为不相等的项目返回不同的哈希码,因为这将使您的字典查找速度更快。
您还应该以正确检查相等实例的方式实现 Equals。
类(引用类型)的默认实现只是比较引用本身。默认情况下,具有完全相同值的两个实例在 Equals 上返回 false(因为它们具有不同的引用)。默认情况下,多个实例也总是返回不同的哈希码。
【讨论】:
字典是一个哈希表。如果两个对象产生相同的哈希值,它只会调用 Equals(object obj)。为您的对象提供良好的哈希函数以避免调用 Equals()。
请记住,哈希部分的复杂度为 O(1),而搜索部分的复杂度在最坏情况下为 O(n),在平均情况下为 O(n/2)。您应该避免生成相同哈希值的对象,否则会线性搜索此对象
【讨论】:
假设您已将自定义引用类型定义为键,您必须:
base.GetHashCode() 方法基于对象的实例标识构建哈希,因此当您将类型的不同实例作为键传递时,不能使用该方法。
为您的哈希返回 0 始终有效的原因是 Dictionary 类首先使用哈希码查找您的密钥所属的存储桶,然后才使用 Equals() 方法来区分实例。如果您打算将自定义类型用作字典键,则不应将 0 作为哈希码返回,因为这会有效地将字典退化为具有 O(n) 查找性能而不是 O(1) 的列表。
您可能还想考虑实现 IComparable 和 IEquatable。
查看以下问题了解更多详情:
【讨论】: