tags:

views:

1600

answers:

3
    class A
    {
        public override int GetHashCode()
        {
            return 1;
        }
    }
    class B : A
    {
        public override int GetHashCode()
        {
            return ((object)this).GetHashCode();
        }
    }

new B().GetHashCode()

this overflows the stack. how can i call Object.GetHashCode from B.GetHashCode()?

edit: B now inherits from A.

+5  A: 

(edit - misread question)

If you want to get the original object.GetHashCode() version; you can't - at least, not unless A makes it available via something like:

protected int GetBaseHashCode() { return base.GetHashCode();}

(and have B call GetBaseHashCode()).

The reason it overflows is that GetHashCode is (obviously) virtual - it doesn't matter if you cast it to object; it still starts at the most-derived implementation in the actual object, i.e. B.GetHashCode() (hence the explosion).

Marc Gravell
Looks like I had misread it too. Good catch.
Welbog
Actually, I thought you can use reflection to call a specific version of a method, even if it is virtual.
LBushkin
@LBushkin - I thought that too; but when I tried it a little while ago (using custom IL and "call" instead of "callvirt") the CLI rejected it, saying it could destabilise the runtime (and that was for a trivial example).
Marc Gravell
+1  A: 

At first it looks like you are right: it is impossible. However i have found a way by "cheating":

return (int)typeof(object).GetMethod("GetHashCode").Invoke(this, null);
usr
+3  A: 

You can use RuntimeHelpers.GetHashCode(object) to get the original hash code of the object:

  class A
  {
    public override int GetHashCode()
    {
      Console.WriteLine("base hashcode is: " + base.GetHashCode());

      return 1;
    }
  }

  class Program
  {
    public static void Main(string[] args)
    {
      A a = new A();

      Console.WriteLine("A's hashcode: " + a.GetHashCode());

      Console.WriteLine("A's original hashcode: " + RuntimeHelpers.GetHashCode(a));
    }
  }

This produces the following result:

base hashcode is: 54267293
A's hashcode: 1
A's original hashcode: 54267293

If you take a look at RuntimeHelpers.GetHashCode(object) in Reflector, you'll see that it calls the internal static method object.InternalGetHashCode(object). If you'd like to know more, have a look at this question regarding the default implementation of GetHashCode.

hmemcpy