C# 字典什么时候出版;TKey,TValue>;调用TKey.Equals()?

C# 字典什么时候出版;TKey,TValue>;调用TKey.Equals()?,c#,.net,dictionary,C#,.net,Dictionary,仅在TKey中覆盖等于,没有帮助 public override bool Equals(object obj) { /* ... */ } Equals()永远不会被调用…假设您已将自定义引用类型定义为键,则必须: 始终将同一对象实例作为键传递到字典中,或 实现一个GetHashCode(),它总是返回相同的值,即使对于不同的实例,Equals()方法也可以比较不同的实例 base.GetHashCode()方法基于对象的实例标识生成哈希,因此当您将一个类型的不同实例作为键传递时,不能使用

仅在
TKey
中覆盖
等于
,没有帮助

public override bool Equals(object obj)
{ /* ... */  }

Equals()
永远不会被调用…

假设您已将自定义引用类型定义为键,则必须:

  • 始终将同一对象实例作为键传递到字典中,或
  • 实现一个GetHashCode(),它总是返回相同的值,即使对于不同的实例,Equals()方法也可以比较不同的实例
  • base.GetHashCode()方法基于对象的实例标识生成哈希,因此当您将一个类型的不同实例作为键传递时,不能使用该方法

    为哈希返回0总是有效的原因是Dictionary类首先使用哈希代码查找密钥所属的bucket,然后才使用Equals()方法来区分实例。如果要将自定义类型的0用作字典键,则不应将其作为哈希代码返回,因为这将有效地将字典退化为具有O(n)查找性能而不是O(1)的列表

    您也可以考虑实现ICM和IEQP。 有关详细信息,请查看以下问题:


    当您查找字典时,事情发生的顺序如下:

  • 字典使用TKey.GetHashCode计算bucket的哈希
  • 然后,它使用该bucket检查所有散列,并对单个对象调用Equals,以确定匹配
  • 如果bucket从不匹配(因为GetHashCode没有被覆盖),那么您将永远不会调用Equals。这就是为什么如果实现了其中一个,就应该始终实现这两个函数的部分原因。如果要在哈希集合中使用对象,就应该重写这两个函数(比只调用base.GetHashCode()更有意义)

    如果要实现一个类,那么应该实现一个GetHashCode例程,该例程为相等的项返回相同的哈希代码。理想情况下,您希望尽可能为不相等的项返回不同的哈希代码,因为这将使您的字典查找更快

    您还应该以正确检查相等实例的方式实现相等


    类(引用类型)的默认实现只是比较引用本身。默认情况下,两个实例具有完全相同的值,等于时返回false(因为它们具有不同的引用)。默认情况下,多个实例也将始终返回不同的哈希代码。

    字典是一个哈希表。只有当两个对象产生相同的散列值时,它才会调用Equals(objectobj)。为对象提供一个好的哈希函数,以避免调用Equals()

    请记住,哈希部分的复杂度为O(1),搜索部分的复杂度在最坏情况下为O(n),在平均情况下为O(n/2)。您应该避免生成相同哈希值的对象,否则将线性搜索这些对象