In relation with my previous post about string.GetHashCode being used in AJAXControlToolkit’s ToolkitScriptManager class, I wanted to talk about object.GetHashCode in general, and string.GetHashCode specifically.

string.GetHashCode documentation states:

“The behavior of GetHashCode is dependent on its implementation, which might change from one version of the common language runtime to another. A reason why this might happen is to improve the performance of GetHashCode.”

The real conclusion from this paragraph is that you shouldn’t base your implementation on string.GetHashCode. But this is a bit too harsh since GetHashCode in general and string.GetHashCode specifically are being used throughout the runtime for internal things.

As long as you don’t share this hash code outside the boundry of the AppDomain its relatively safe to use.

The reason you cannot (or should I say should not) pass it across an AppDomain boundry is that the basic implemenetation of object.GetHashCode is to return an integer representing the reference id of the object in the .NET runtime. That reference is not guarenteed to be the same for the same object in a different appdomain/process/machine.

In the case of string.GetHashCode, where the implementation differ from the default one, you can pass it across AppDomains and even machines (though you shouldn’t count on that as well!) as long as they are in the same architecture, i.e., 32bit to 32bit and 64bit to 64bit.

All in all, the most recommend way of using x.GetHashCode is simply not using it at all. There are numerous implementations of hashing functions built into .NET (such as MD5, SHA1, SHA256, etc) which are more consistent but may be a bit more expensive computation wise.

For all your outward facing code I would recommend using one of the common and known hashing functions specifically if this is a case where the code on the other side needs to recompute the hash and compare it with the hash value being passed.

If you mix and match 32 bit machines/processes with 64 bit machines/processes in an ASP.NET load balanced environment and you are using the AJAXControlToolkit ToolkitScriptManager class you might end up with the following error:

Message: Assembly “AjaxControlToolkit, Version=1.0.10920.32880, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e” does not contain a script with hash code “9ea3f0e2″.
Stack trace: at AjaxControlToolkit.ToolkitScriptManager.DeserializeScriptEntries(String serializedScriptEntries, Boolean loaded)

at AjaxControlToolkit.ToolkitScriptManager.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

The reason is that the request being sent to retrieve the combined javascripts of the control used in the page contains a hash code that is used internally. That hash code is being generated from the script’s name using the default string.GetHashCode function which returns different values for 32 bit and 64 bit processes.

If your 64 bit process creates the javascript include call which contains the 64 bit hash code and the request will eventually reach the 32 bit process/machine you will get this error since the hash value will not be found internally and vice versa.

There is an open issue about this in CodePlex since late January but as of the time of this post, the latest source version in CodePlex doesn’t have a fix for this.