» string.GetHashCode() returns different hashes on 64bit and 32bit machines


64bit, ASP.NET, C#, Microsoft, Programmeren

string.GetHashCode() returns different hashes on 64bit and 32bit machines

09.25.09 | 82 Comments

First of all, you’re not supposed to use string.GetHashCode() (object.GetHashCode() to be exact) to store persistent hashes in databases or on file. The method is used mainly to generate hashes for Hashtables. And msdn documentation points out that hashes generated by object.GetHashCode may differ in different environments, machines, framework version etc.. All depends on the object and its implementation of the method. http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

As it turns out the string.GetHashCode() has no random factor and is fully based on the characters in the string. This means it will always return the same value for the same string It also has a good spread and on top of that it return int32 values instead of  some horrible base64 encoded string. It can therefor be very usefull for storing word hashes in search tables. I used string.GetHashCode() to generate wordhashes for searchbarrels. All of this worked very well from .NET 1.1 over .NET 2.0 to 3.0 and 3.5. 

Last week however we installed a beautifull new frontend: dual quad core, 16 GB ram AND OFCOURCE 64 BIT! Everything worked fine execpt for the searchbarrels. No errors or crashes just no result. Some log digging pointed to the hashes. Apparently string.GetHashCode() return different hashes in 64bit then in 32bit. This turned out to be a rather big problem. google didn’t help much at first so we turned to reflection. As we suspected the System.String implementation of GetHashCode() is different in the 64bit framework. 

This is very good news because now it has nothing to do with the 64bit itself and we can simply create our own method or extension method that will still generate the same hashes even on a 64bit machine

    /// <summary>
    /// Similar to String.GetHashCode but returns the same 
    /// as the x86 version of String.GetHashCode for x64 and x86 frameworks.
    /// </summary>
    /// <param name="s"></param>
    /// <returns></returns>
    public static unsafe int GetHashCode32(string s)
        fixed (char* str = s.ToCharArray())
            char* chPtr = str;
            int num = 0x15051505;
            int num2 = num;
            int* numPtr = (int*)chPtr;
            for (int i = s.Length; i > 0; i -= 4)
                num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
                if (i <= 2)
                num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1];
                numPtr += 2;
            return (num + (num2 * 0x5d588b65));


have your say

Add your comment below, or trackback from your own site. Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



16 queries. 0,747 seconds.