The RuntimeHelpers.GetHashCode(object)
method allows generating hash codes based on the identity of an object. MSDN states:
The RuntimeHelpers.GetHashCode method always calls the Object.GetHashCode method non-virtually, even if the object's type has overridden the Object.GetHashCode method.
[MethodImpl(MethodImplOptions.InternalCall)]
[SecuritySafeCritical]
public static extern int GetHashCode(object o);
However, when inspecting the Object.GetHashCode()
method using Reflector (.NET 4.0), we'll see the following code:
public virtual int GetHashCode()
{
return RuntimeHelpers.GetHashCode(this);
}
This makes me believe that the MSDN documentation is wrong, since calling Object.GetHashCode
from within the RuntimeHelpers.GetHashCode(object)
would cause a stack overflow.
So what is the actual behavior of RuntimeHelpers.GetHashCode(object)
and how does it work? How does it calculate the hash?
From your own question, it looks like
RuntimeHelpers.GetHashCode(Object)
is really the implementation of the non-overriddenObject.GetHashCode()
.I think the MSDN documentation is trying to describe the behaviour, not the implementation. The key point:
RuntimeHelpers
returns the default implementation that you would get wereobject.GetHashCode()
not overridden.This is really useful if, for example, you want to build a reference equality lookup, even for types that have overridden
Equals
andGetHashCode
. I do this in a serializer that I maintain, usingRuntimeHelpers.GetHashCode()
andObject.ReferenceEquals
.The point is that
object.GetHashCode()
can be overridden - and frequently is, e.g. bystring
. That means you can't find out the "identity hash code" which the default implementation ofobject.GetHashCode()
returns.This can be useful if you want to implement an equalty comparer (e.g. for a
HashSet
) which only considers object identity.For example:
Then:
EDIT: Just to clarify a bit...
The observed behaviour is that the value returned from
RuntimeHelpers.GetHashCode(object)
is the same as the value which would be returned from a non-virtual call toObject.GetHashCode()
. (You can't write that non-virtual call in C# easily.)As for how it works - that's an implementation detail :) It doesn't really matter IMO which way round things occur (what calls what). The important thing is the documented behaviour, which is correct. Heck, different versions of mscorlib could implement this differently - it wouldn't matter at all from a user's point of view. Without decompilation, you shouldn't be able to tell the difference.
It would (IMO) have been far more confusing for
Object.GetHashCode
to have been documented in terms ofRuntimeHelpers.GetHashCode()
.Strange, when I look at System.Object.GetHashCode via Reflector I see
and for runtimehelper:
Perhaps it's a framework difference? I'm looking at 2.0 assemblies.