在.NET中使用String.GetHashCode()的哈希质量和稳定性?

我想知道.NET中的String.GetHashCode()实现产生的哈希质量哈希稳定性

关于质量,我专注于算法方面(因此,哈希的质量,因为它影响大型哈希表,而不是安全问题)。

然后,关于稳定性,我想知道从一个.NET版本到下一个版本可能出现的潜在版本问题。

关于这两个方面的一些亮点将非常感激。

我不能给你任何关于质量的细节(虽然我认为这是非常好的,因为字符串是框架的核心类之一,很可能被用作哈希键)。

但是,关于稳定性,在不同版本的框架上生成的哈希代码不保证是相同的,并且它在过去已经改变,所以你绝对不能依赖于版本之间的哈希代码是稳定的( 参见此处它在1.1和2.0之间变化的引用 。 实际上,它甚至在同一框架版本的32位和64位版本之间也有所不同; 来自文档 :

GetHashCode返回的值取决于平台。 对于特定的字符串值,它在32位和64位版本的.NET Framework上有所不同。

这是一个老问题,但我想通过提及这个关于哈希质量的微软错误做出贡献。

简介:在64b上, 当字符串包含’\ 0’字节时哈希质量非常低 。 基本上,只会对字符串的开头进行哈希处理。

如果像我一样,你必须使用.Net字符串来表示二进制数据作为高性能字典的关键,你需要知道这个bug。

太糟糕了,这是一个WONTFIX …作为一个旁注,我不明白当代码包括时,他们怎么能说修改哈希码是一个重大变化

 // We want to ensure we can change our hash function daily. // This is perfectly fine as long as you don't persist the // value from GetHashCode to disk or count on String A // hashing before string B. Those are bugs in your code. hash1 ^= ThisAssembly.DailyBuildNumber; 

并且无论如何,在x86 / 64b中哈希码已经不同了。

我刚刚遇到了一个相关的问题。 在我的一台计算机上(64位一台)我遇到了一个问题,我追踪到2个不同的对象是相同的,除了(存储的)哈希码。 该hashcode是从一个字符串……相同的字符串创建的!

m_storedhash = astring.GetHashCode();

我不知道这两个对象是如何以不同的哈希码结束的,因为它们来自同一个字符串但是我怀疑发生了什么是在同一个.NET exe中,我依赖的类库项目之一被设置为x86而另一个到ANYCPU,其中一个对象是在x86类lib中的方法中创建的,另一个对象(相同的输入数据,相同的所有内容)是在ANYCPU类库中的方法中创建的。

那么,这听起来似乎有道理:在内存中的相同可执行文件中(不在进程之间),一些代码可以使用x86 Framework的string.GetHashCode()和其他代码x64 Framework的string.GetHashCode()运行吗?

我知道这并不包含您指定的质量和稳定性的含义,但值得注意的是,散列非常大的字符串会产生OutOfMemoryException。

https://connect.microsoft.com/VisualStudio/feedback/details/517457/stringcomparers-gethashcode-string-throws-outofmemoryexception-with-plenty-of-ram-available

哈希码的质量足以满足其预期目的,即当您将字符串用作字典中的键时,它们不会导致太多冲突。 我怀疑它只会使用整个字符串来计算哈希码,如果字符串长度相当短,对于巨大的字符串,它可能只使用第一部分。

不保证版本之间的稳定性。 文档清楚地表明散列算法可能会从一个版本更改为下一个版本,因此散列码是短期使用的。