我想知道.NET中String.GetHashCode()
实现产生的哈希质量和哈希稳定性?
关于质量,我专注于算法方面(因此,哈希的质量因为它影响大型哈希表,而不是安全问题)。
然后,关于稳定性,我想知道从一个.NET版本到下一个版本可能出现的版本问题。
非常感谢这两方面的一些亮点。
答案 0 :(得分:19)
我无法向您提供有关质量的任何细节(尽管我认为它非常好,因为字符串是框架的核心类之一,很可能被用作散列键)。
但是,关于稳定性,在不同版本的框架上生成的哈希代码不保证是相同的,并且它在过去已经改变,所以你绝对不能依赖于版本之间的哈希代码是稳定的( see here for a reference that it changed between 1.1 and 2.0)。实际上,它甚至在相同框架版本的32位和64位版本之间也有所不同; from the docs:
GetHashCode返回的值与平台有关。对于特定的字符串值,它在32位和64位版本的.NET Framework上有所不同。
答案 1 :(得分:13)
这是一个老问题,但我想通过提及this microsoft bug about hash quality来做出贡献。
摘要:在64b上,当字符串包含'\ 0'字节时,哈希质量非常低。基本上,只会对字符串的开头进行哈希处理。
如果像我一样,你必须使用.Net字符串来表示二进制数据作为高性能字典的关键,你需要注意这个错误。
太糟糕了,这是一个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中哈希码已经不同了。
答案 2 :(得分:2)
我刚刚遇到了一个相关的问题。在我的一台计算机上(64位一台)我遇到了一个问题,我追踪到2个不同的对象是相同的,除了(存储的)哈希码。该哈希码是从字符串......相同的字符串创建的!
m_storedhash = astring.GetHashCode();
我不知道这两个对象如何以不同的哈希码结束,因为它们来自同一个字符串但是我怀疑发生了什么是在同一个.NET exe中,我所依赖的类库项目之一已被设置为x86和另一个到ANYCPU,其中一个对象是在x86类lib中的方法中创建的,另一个对象(相同的输入数据,相同的所有内容)是在ANYCPU类库中的方法中创建的。
那么,这听起来似乎是合理的:在内存中的相同可执行文件中(不在进程之间),一些代码可以使用x86 Framework的string.GetHashCode()和其他代码运行x64 Framework的string.GetHashCode()?
答案 3 :(得分:2)
我知道这并不包含您指定的质量和稳定性的含义,但值得注意的是,散列非常大的字符串会产生OutOfMemoryException。
答案 4 :(得分:0)
哈希码的质量足以满足其预期目的,即当您将字符串用作字典中的键时,它们不会导致太多冲突。我怀疑如果字符串长度相当短,它只会使用整个字符串来计算哈希码,对于巨大的字符串,它只会使用第一部分。
不保证版本之间的稳定性。文档清楚地表明散列算法可能会从一个版本更改为下一个版本,因此散列码是短期使用的。