C# 我们什么时候为字典执行GetHashCode()?
我使用字典(TKey,TValue)有很多用途。但是我没有遇到任何实现GetHashCode()的场景,我相信这是因为我的键是int和string等主要类型。 我很想知道在什么情况下(真实世界的例子),人们应该使用自定义对象作为键,从而实现GetHashCode()Equals()等方法C# 我们什么时候为字典执行GetHashCode()?,c#,.net,C#,.net,我使用字典(TKey,TValue)有很多用途。但是我没有遇到任何实现GetHashCode()的场景,我相信这是因为我的键是int和string等主要类型。 我很想知道在什么情况下(真实世界的例子),人们应该使用自定义对象作为键,从而实现GetHashCode()Equals()等方法 而且,使用自定义对象作为密钥是否需要实现这些功能?一个示例是,当您需要创建复合密钥(即包含多个数据段的密钥)时。该复合键将是需要重写这些方法的自定义类型 例如,假设您有一个内存中的地址记录缓存,您想检查一个地址
而且,使用自定义对象作为密钥是否需要实现这些功能?一个示例是,当您需要创建复合密钥(即包含多个数据段的密钥)时。该复合键将是需要重写这些方法的自定义类型 例如,假设您有一个内存中的地址记录缓存,您想检查一个地址是否在缓存中,以节省昂贵的数据库检索行程。也可以说,地址在street 1和zip code字段方面是唯一的。您可以使用以下内容实现缓存:
class AddressCacheKey
{
public String StreetOne { get; set; }
public String ZipCode { get; set; }
// overrides for Equals and GetHashCode
}
及
静态字典缓存;
由于您的
AddressCacheKey
类型覆盖了Equals
和GetHashCode
方法,因此它们是字典中键的一个很好的候选者,您可以确定是否需要访问数据库以基于多个数据段检索记录。当默认值(参考相等性测试)不满足要求时,覆盖Equals
和GetHashCode
。例如,如果密钥的类型是自定义类型,并且希望两个密钥被视为相等,即使它们不是自定义类型的同一实例,也会发生这种情况
例如,如果您的密钥与
class Point {
public int X { get; set; }
public int Y { get; set; }
}
你想要两个
点
s如果他们的X
s相等,他们的Y
s相等,那么你需要覆盖Equals
和GetHashCode
这里有两个问题
对于2),只要需要从对象到其他类型进行固定时间的查找,就应该使用对象。由于GetHashCode()返回一个数值,集合存储引用,因此在Int或字符串上使用对象(请记住字符串是一个对象)不会受到任何惩罚。只需澄清一点:关于
字典
和GetHashCode()
:Dictionary使用GetHashCode来确定两个键是否相等,即如果
是自定义类型,您应该小心地实现GetHashCode()
。正如Andrew Hare指出的,如果您有一个明确标识自定义对象的简单类型,那么这很容易。如果您有一个组合标识符,它会变得更复杂一些
例如,把复数看作<代码> TKey < /代码>。复数由其实部和虚部决定。两者都是简单类型,例如double
。但是,如果两个复数相等,您将如何识别?您可以为自定义复杂类型实现GetHashCode()
,并将这两个标识部分结合起来
你可以进一步阅读后者
更新
根据Ergwun的评论,我检查了字典的行为。添加,特别是TKey
实现的Equals(object)
和GetHashCode()
。我
我必须承认,我对结果感到相当惊讶
给定类型为TKey
的两个对象k1
和k2
,类型为TValue
的两个任意对象v1
和v2
,以及类型为dictionary
的空字典d
,这是在将带有键k1的v1
添加到d
和带有键k2的v2
时发生的情况(取决于TKey.Equals(object)
和TKey.GetHashCode()
的实现):
结论:我错了,因为我最初认为第二种情况(其中Equals
返回false
,但两个关键对象都有相同的哈希代码)会引发ArgumentException
。但正如第三个案例所示,字典在某种程度上确实使用了GetHashCode()
。无论如何,这似乎是一个很好的建议,即两个类型相同且相等的对象必须返回相同的哈希代码,以确保实例Dictionary
正常工作。-1 Dictionary不使用GetHashCode()
来确定两个键是否相等。也就是说,字典可以包含其键具有相同哈希代码的单独条目。字典可能效率较低,但仍能工作。是的,您应该确保相等的对象返回相同的哈希代码(请参阅)。对于字典,如果1)我就地编辑对象并将point.X
交换为point.Y
,那么Equals和GetHashCode需要是什么?是否必须删除该值,并将其重新添加到字典中?读取的可能重复项这不是Int32 A对象,因为它派生自System.object派生的System.ValueType。读取该值
class Point {
public int X { get; set; }
public int Y { get; set; }
}
k1.Equals(k2) k1.GetHashCode() == k2.GetHashCode() d.Add(k2, v2)
false false ok
false true ok
true false ok
true true System.ArgumentException