令我惊讶的是,下面的方法在debug和release中产生了不同的结果:
int result = "test".GetHashCode();
有什么方法可以避免这种情况吗?
我需要一种可靠的方法来散列字符串,我需要在调试和发布模式下保持一致的值。如果可能的话,我想避免编写自己的散列函数。
为什么会这样?
仅供参考,反射器给了我:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail), SecuritySafeCritical]
public override unsafe int GetHashCode()
{
fixed (char* str = ((char*) this))
{
char* chPtr = str;
int num = 0x15051505;
int num2 = num;
int* numPtr = (int*) chPtr;
for (int i = this.Length; i > 0; i -= 4)
{
num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
if (i <= 2)
{
break;
}
num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
numPtr += 2;
}
return (num + (num2 * 0x5d588b65));
}
}
答案 0 :(得分:9)
GetHashCode()
不您应该使用什么来散列字符串,几乎100%的时间。在不知道你在做什么的情况下,我建议你使用实际的哈希算法,比如SHA-1:
using(System.Security.Cryptography.SHA1Managed hp = new System.Security.Cryptography.SHA1Managed()) {
// Use hp.ComputeHash(System.Text.Encoding.ASCII (or Unicode, UTF8, UTF16, or UTF32 or something...).GetBytes(theString) to compute the hash code.
}
更新:对于更快一点的东西,还有SHA1Cng
,这比SHA1Managed
要快得多。
答案 1 :(得分:3)
这是一种比SHA快得多的更好的方法,您可以用它替换修改后的GetHasCode:C# fast hash murmur2
有几种实现具有不同级别的“非托管”代码,因此如果您需要完全托管,那么它就在那里,如果您可以使用不安全的,那么它也是。
答案 2 :(得分:0)
/// <summary>
/// Default implementation of string.GetHashCode is not consistent on different platforms (x32/x64 which is our case) and frameworks.
/// FNV-1a - (Fowler/Noll/Vo) is a fast, consistent, non-cryptographic hash algorithm with good dispersion. (see http://isthe.com/chongo/tech/comp/fnv/#FNV-1a)
/// </summary>
private static int GetFNV1aHashCode(string str)
{
if (str == null)
return 0;
var length = str.Length;
// original FNV-1a has 32 bit offset_basis = 2166136261 but length gives a bit better dispersion (2%) for our case where all the strings are equal length, for example: "3EC0FFFF01ECD9C4001B01E2A707"
int hash = length;
for (int i = 0; i != length; ++i)
hash = (hash ^ str[i]) * 16777619;
return hash;
}
我猜这个实现比发布的不安全的here要慢。但它更简单,更安全。如果不需要超高速,效果很好。