String.GetHashCode\'s behavior is depend on the program architecture. So it will return one value in x86 and one value on x64. I have a test application which must run in x8
The following exactly reproduces the default String hash codes on .NET 4.7 (and probably earlier). This is the hash code given by:
- Default on a
String
instance:"abc".GetHashCode()
StringComparer.Ordinal.GetHashCode("abc")
- Various
String
methods that takeStringComparison.Ordinal
enumeration.System.Globalization.CompareInfo.GetStringComparer(CompareOptions.Ordinal)
Testing on release builds with full JIT optimization, these versions modestly outperform the built-in .NET code, and have also been heavily unit-tested for exact equivalence with .NET
behavior. Notice there are separate versions for x86 versus x64. Your program should generally include both; below the respective code listings is a calling harness which selects the appropriate version at runtime.
x86 - (.NET running in 32-bit mode)
static unsafe int GetHashCode_x86_NET(int* p, int c)
{
int h1, h2 = h1 = 0x15051505;
while (c > 2)
{
h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++;
h2 = ((h2 << 5) + h2 + (h2 >> 27)) ^ *p++;
c -= 4;
}
if (c > 0)
h1 = ((h1 << 5) + h1 + (h1 >> 27)) ^ *p++;
return h1 + (h2 * 0x5d588b65);
}
x64 - (.NET running in 64-bit mode)
static unsafe int GetHashCode_x64_NET(Char* p)
{
int h1, h2 = h1 = 5381;
while (*p != 0)
{
h1 = ((h1 << 5) + h1) ^ *p++;
if (*p == 0)
break;
h2 = ((h2 << 5) + h2) ^ *p++;
}
return h1 + (h2 * 0x5d588b65);
}
Calling harness / extension method for either platform (x86/x64):
readonly static int _hash_sz = IntPtr.Size == 4 ? 0x2d2816fe : 0x162a16fe;
public static unsafe int GetStringHashCode(this String s)
{
/// Note: x64 string hash ignores remainder after embedded '\0'char (unlike x86)
if (s.Length == 0 || (IntPtr.Size == 8 && s[0] == '\0'))
return _hash_sz;
fixed (char* p = s)
return IntPtr.Size == 4 ?
GetHashCode_x86_NET((int*)p, s.Length) :
GetHashCode_x64_NET(p);
}