Ian*_*ose 44 .net c# database hashcode gethashcode
引用 Eric Lippert的GetHashCode指南和规则:
规则:GetHashCode的消费者不能依赖它随着时间的推移或跨appdomains的稳定性
假设您有一个Customer对象,其中包含一系列字段,如Name,Address等.如果在两个不同的进程中使用完全相同的数据生成两个这样的对象,则它们不必返回相同的哈希代码.如果你在星期二的一个进程中创建这样一个对象,关闭它,并在星期三再次运行程序,哈希码可能会有所不同.
这在过去曾经被人咬伤过.System.String.GetHashCode的文档特别指出,两个相同的字符串在CLR的不同版本中可以具有不同的哈希码,实际上它们也是如此.不要在数据库中存储字符串哈希并期望它们永远是相同的,因为它们不会.
那么创建一个可以存储在数据库中的字符串的HashCode的正确方法是什么?
(请告诉我,我不是第一个在我写的软件中留下这个错误的人!)
Jon*_*eet 71
它取决于您希望哈希具有哪些属性.例如,你可以写这样的东西:
public int HashString(string text)
{
// TODO: Determine nullity policy.
unchecked
{
int hash = 23;
foreach (char c in text)
{
hash = hash * 31 + c;
}
return hash;
}
}
Run Code Online (Sandbox Code Playgroud)
只要您记录这是计算哈希的方式,那就是有效的.它绝不是加密安全或类似的东西,但你可以毫无问题地坚持它.在序数意义上绝对相等的两个字符串(即没有应用文化相等等,完全逐字符相同)将使用此代码生成相同的散列.
当您依赖于未记录的散列时会出现问题- 即某些东西遵循GetHashCode()但不能保证在不同版本之间保持相同......就像string.GetHashCode().
像这样编写和记录你自己的哈希有点像说,"这个敏感的信息是用MD5(或其他)散列的".只要它是一个定义明确的哈希,那很好.
编辑:其他答案建议使用加密哈希,如SHA-1或MD5.我要说的是,在我们知道需要加密安全性而不仅仅是稳定性之前,没有必要经历将字符串转换为字节数组并对其进行散列的严格要求.当然,如果哈希值是指用于任何与安全有关的,行业标准的哈希正是你应该达到什么样的.但在问题的任何地方都没有提到.
以下是.NET计算64位系统的字符串哈希码的当前方式的重新实现.这不会像真实GetHashCode()那样使用指针,因此它会稍微慢一点,但它确实使内部更改更具弹性string,这将提供比Jon Skeet版本更均匀分布的哈希代码,这可能会导致更好的词典查找时间.
public static class StringExtensionMethods
{
public static int GetStableHashCode(this string str)
{
unchecked
{
int hash1 = 5381;
int hash2 = hash1;
for(int i = 0; i < str.Length && str[i] != '\0'; i += 2)
{
hash1 = ((hash1 << 5) + hash1) ^ str[i];
if (i == str.Length - 1 || str[i+1] == '\0')
break;
hash2 = ((hash2 << 5) + hash2) ^ str[i+1];
}
return hash1 + (hash2*1566083941);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14311 次 |
| 最近记录: |