字符串的持久哈希码

时间:2016-04-25 15:53:32

标签: c# string hash hashcode gethashcode

我想为字符串生成一个整数哈希码,它将永远保持不变;即相同的字符串应始终产生相同的哈希码。

散列不必是加密安全的,它不会用于密码或敏感数据。

我的第一次尝试是使用.net框架string.GetHashCode()函数。 但是在阅读资料后我发现了以下内容:

// 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;

这似乎表明哈希码不会保持不变。

如果是这样,框架是否有另一种方法来生成可重复的哈希码?或者GetHashCode的代码是否是实现我自己的合理起点?

我正在寻找尽可能轻巧和快速的东西 我发现System.Security.Cryptography.MD5,但对于一个简单的int32哈希码来说这似乎有点过头了,我担心开销。至少它需要从字符串转换为字节数组,从字节数组转换为int,并为每个散列创建新的MD5()对象,或者管理某些静态共享MD5对象()。

1 个答案:

答案 0 :(得分:20)

没有内置的,交叉版本稳定的方式来获取字符串的哈希码。

您可以复制现有的GetHashCode()代码,但不包括将内部版本号添加为种子的部分,也不要使用不安全的调用来保护自己免受实现细节更改的影响。

以下是64bit GetHashCode()的完全托管版本,它不使用任何随机化,并且将为所有未来版本的.NET返回相同的值(只要int ^ char的行为永远不会更改)

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);
        }
    }
}