.NET字符串哈希函数是否可移植?

15

可能是重复问题:
如何在 .net (c#) 中创建一个字符串的哈希码,以便安全地存储在数据库中?

我使用C# 4.0,并通过调用以下方法获取字符串哈希值:

"my string".GetHashCode()

此调用生成的代码会被存储到数据库中以备将来使用。这个哈希码用于查找一些子集字符串并进行相等比较。

问题如下:

  1. 这是一个标准的哈希计算吗?我可以假设在不同的环境中,比如 .Net 3.0 或未来的 .Net 版本中,可以计算出相同的哈希吗?
  2. 能否通过编写 Java、PL/SQL、Ruby 等自己的代码来计算相同的哈希函数?
  3. 我能否假设今天生成的哈希在相同的环境下明天也是相同的?例如,当我关闭计算机并再次运行程序或更改区域设置或其他设置时?
  4. 可移植性的限制是什么?
  5. 我知道我可以自己完成,但可能会提供某种移植性吗?

13
你的问题的答案是“不”,“不”,“不”,“不”,“不”,根本没有“可移植性”,也没有“可移植性”。在任何情况下,你描述的事情都不应该去做。 - Eric Lippert
4个回答

19

来自 MSDN:

GetHashCode 方法的默认实现不能保证对于不同的对象返回唯一的哈希值。此外,.NET Framework 也不能保证 GetHashCode 方法的默认实现,且它返回的值在不同版本的 .NET Framework 中是相同的。因此,此方法的默认实现不能用作哈希目的的唯一对象标识符。

因此,不能假设由 GetHashCode 生成的值是稳定的。这不仅是理论上的问题,还会出现实际情况 - 我们曾经见过该值在过去发生变化

如果你想要一个稳定的哈希值,你需要自己生成它。


默认实现 - String 使用默认实现吗?老实说我不知道,我只是不会期望它使用(因为它们在哈希表中被按值处理)。 - user395760
3
System.String 重写了 GetHashCode 方法,并在其文档中包含类似的说明:GetHashCode 的行为取决于其实现,它可能会从一个公共语言运行时版本到另一个版本改变。这种情况发生的原因之一是为了提高 GetHashCode 的性能。 同时 GetHashCode 返回的值依赖于平台,.NET Framework 的 32 位和 64 位版本返回的值不同。 - Michael Petrotta

18

1
直接从Eric Lippert本人那里获取知识,这是非常有价值的。 - Chris Laplante

3

2
不。它不是可移植的。你不应该将这种方法用于除了平衡哈希树之外的任何其他情况。它的实现在框架的不同版本之间有所改变,并且在32位/64位CLR上的行为也不同。
Eric Lippert在博客文章中介绍了关于此函数的规则和适当用法。
相反,你应该使用{{link2:SHA1Managed}}将哈希插入到数据库中。

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