C#: 相同的对象必须具有相同的哈希码吗?

5
假设我有两个对象,分别叫做KM
if(K.Equals(M))
{

}

如果这是真的,KMHashCode总是相同的吗?还是这取决于编程语言?

2
你的问题已经在你提供的MSDN上的HashCode文章中得到了回答。 - Sebastian P.R. Gingter
更多内容请阅读海盗法典 - Anthony Pegram
7个回答

7
< p > GetHashCode() 方法的契约要求使用它,但由于任何人都可以制作自己的实现,因此无法保证其可靠性。

许多类(尤其是哈希表)需要它以正确地发挥作用。

如果您正在实现一个类,请确保两个相等的对象具有相同的哈希码。

如果您正在实现某个实用程序方法/类,则可以假定两个相等的对象具有相同的哈希码(如果不是这样,则是另一个类而不是您的类出了问题)。

如果您正在实现具有安全影响的东西,则不能这样假设。


如果 K.Equals(M) 但是 GetHashCode() 的值不同,则该类存在缺陷,可能不应该使用。 - Paweł Obrok

2
如果是这样的话,K和M总是具有相同的HashCode吗?
是的。
或者更确切地说,应该是这样的。哈希码的使用者(例如容器)可以假设相等的对象具有相等的哈希码,或者说不相等的哈希码意味着对象不相等。(不相等的对象可以具有相同的哈希码:可能的对象比哈希码多,因此必须允许这种情况。)
还是要看编程语言吗?
不需要。

1

是的,它应该返回相同的哈希码。

我认为这与编程语言无关。但是如果其他程序没有正确实现它,就不能保证。

GetHashCode返回一个基于当前实例的值,适用于哈希算法和数据结构,例如哈希表。两个相同类型且相等的对象必须返回相同的哈希码,以确保System.Collections.HashTable和System.Collections.Generic.Dictionary的实例正常工作。


它不是必须的,但应该这样做。有时不同的对象具有相同的哈希值,这是一种情况。 - sll
但是,不同的对象可能具有相同的哈希码,但相等的对象不应具有不同的哈希码。 - Johnny5

1
如果是这样,K和M的HashCode总是相同的吗?
是的。除非它们有一个被恶意覆盖的Equals方法。但那将被视为破损的。
但请注意,反过来并不成立, 如果K和M具有相同的HashCode,则仍可能出现K.Equals(M)== false的情况。

@Soner:不,那是另一个概念。哈希码允许发生碰撞,这不符合Set的描述。 - H H

0

这取决于对象的Equals实现。它可能在幕后使用GetHashCode,但也可能不会。因此,如果您有一个具有自定义Equals实现的对象,则两个对象的HashCode可能会不同。


2
如果是这种情况,那么该类型违反了 GetHashCode 的契约。 - Jon Skeet

0
在你的应用程序中,哈希码必须唯一地标识对象的实例。这是 .NET 平台的一部分,因此无论你使用哪种 .NET 语言编写,哈希码值都应该可以正常工作。

1
哈希码不能保证唯一性。借用Eric Lippert的说法,大约有40亿种可能的哈希码结果和无限可能的对象,如字符串。最好的情况是,哈希码可以缩小对象范围,但不应期望匹配一个且仅一个对象。 - Anthony Pegram

0

GetHashCode() 可能会为不同的对象返回相同的哈希值。在 GetHashCode() 返回相同值的情况下,您应该使用 Equals() 来比较对象,而不是 GetHashCode()。实现 Equals() 应该考虑另一个对象的相等性检查。

哈希数据结构可以通过使用冲突解决算法来处理这种情况。

来自 wikipedia

当对大量可能键的随机子集进行哈希时,哈希冲突几乎是不可避免的。例如,如果将 2,500 个键哈希到一百万个桶中,即使具有完美均匀的随机分布,根据生日问题,至少有两个键被哈希到相同的插槽的概率为 95%。

因此,大多数哈希表实现都有一些冲突解决策略来处理这种情况。下面描述了一些常见的策略。所有这些方法都要求将键(或指向它们的指针)与相关值一起存储在表中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接