The point is that object.GetHashCode()
can be overridden - and frequently is, e.g. by string
. That means you can't find out the "identity hash code" which the default implementation of object.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:
public class IdentityComparer<T> : IEqualityComparer<T> where T : class
{
public bool Equals(T x, T y)
{
// Just for clarity...
return object.ReferenceEquals(x, y);
}
public int GetHashCode(T x)
{
// The nullity check may be unnecessary due to a similar check in
// RuntimeHelpers.GetHashCode, but it's not documented
return x == null ? 0 : RuntimeHelpers.GetHashCode(x);
}
}
Then:
string x = "hello";
string y = new StringBuilder("h").Append("ello").ToString();
Console.WriteLine(x == y); // True (overloaded ==)
Console.WriteLine(x.GetHashCode() == y.GetHashCode()); // True (overridden)
IdentityComparer<string> comparer = new IdentityComparer<string>();
Console.WriteLine(comparer.Equals(x, y)); // False - not identity
// Very probably false; not absolutely guaranteed (as ever, collisions
// are possible)
Console.WriteLine(comparer.GetHashCode(x) == comparer.GetHashCode(y));
EDIT: Just to clarify a bit...
So what is the actual behavior of RuntimeHelpers.GetHashCode(object) and how does it work?
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 to Object.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 of RuntimeHelpers.GetHashCode()
.
base.*
for example. In most scenarios, usingcall
on a virtual method will make the CLI shout loudly at you - it isn't allowed, regardless of the language of the caller. – Interplead