29
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.

3
  • 3
    Did you mean to have class B inherit from class A? Commented Jun 17, 2009 at 11:54
  • @AakashM - good spot! I mentally inserted it without noticing it isn't there; I think we can assume it should be... Commented Jun 17, 2009 at 11:56
  • 3
    This is not legal in C#. Is it possible to redesign your class hierarchy so that derived types do not need to know about the implementation details of all of their base types? Commented Jun 17, 2009 at 15:18

4 Answers 4

21

(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).

Sign up to request clarification or add additional context in comments.

4 Comments

Actually, I thought you can use reflection to call a specific version of a method, even if it is virtual.
@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).
You could blatantly cheat by creating a DynamicMethod. Something like Dogett's answer to a similar question
Try this answer to a similar question: quick, easy, and you don't need to touch the intermediate class!
14

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.

Comments

7

I'm using an external library and I wanted to call the base.base also (because of a bug in certain case). After some research I came across this page http://www.rsdn.ru/forum/dotnet/475911.aspx

It's quite simple: You define a delegate using the base class you want to call your method and set the object pointer to *this (or the object you want)

So, the important code is:

public delegate void MD();

public void Test() {
        // A is the base class you want to call the method.
        A a = new A();
        // Create your delegate using the method name "M" with the instance 'a' of the base class
        MD am = (MD)Delegate.CreateDelegate(typeof(MD), a, "M");
        // Get the target of the delegate and set it to your object (this in most case)
        am.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance BindingFlags.NonPublic).SetValue(am, this);
        // call the method using the delegate.
        am();
    }

1 Comment

"quite simple" is not what I thought when I read the code but it works like a charm :-) !
0

If you can modify the code of the sub-sub class then you can implement the functionality of the sub-sub-method with a static method. This static (public) method has as first parameter an object of the class. That way you can call it from everywhere.

class A
{
    public static int CalcHashCode(A obj)
    {
        return 1;
    }

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.