Как вызвать метод базового класса второго уровня, например base.base.GetHashCode()

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

new B().GetHashCode()

это переполняет стек. Как я могу вызвать Object.GetHashCode() из B.GetHashCode()?

edit: B теперь наследуется от A.

Ответ 1

(изменить - неверный вопрос)

Если вы хотите получить оригинальную версию object.GetHashCode(); вы не можете - по крайней мере, если только A не делает его доступным через что-то вроде:

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

(и имеет B вызов GetBaseHashCode()).

Причина, по которой он переполняется, заключается в том, что GetHashCode (очевидно) виртуальный - неважно, добавите ли вы его в object; он все еще начинается с самой производной реализации в фактическом объекте, т.е. B.GetHashCode() (отсюда и взрыв).

Ответ 2

Вы можете использовать RuntimeHelpers.GetHashCode(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 hashcode: " + a.GetHashCode());

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

Это приводит к следующему результату:

base hashcode: 54267293
 Хэш-код: 1
 Исходный хэш-код: 54267293

Если вы посмотрите на RuntimeHelpers.GetHashCode(object) в Reflector, вы увидите, что он вызывает внутренний статический метод object.InternalGetHashCode(object). Если вы хотите узнать больше, посмотрите этот вопрос относительно реализации GetHashCode по умолчанию.

Ответ 3

Я использую внешнюю библиотеку, и я хотел также вызвать base.base(из-за ошибки в определенном случае). После некоторых исследований я наткнулся на эту страницу http://www.rsdn.ru/forum/dotnet/475911.aspx

Это довольно просто: вы определяете делегата, используя базовый класс, который хотите вызвать свой метод, и установите указатель на объект * this (или нужный объект)

Итак, важный код:

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();
    }

Ответ 4

Если вы можете изменить код под-подкласса, то вы можете реализовать функциональность под-под-метода со статическим методом. Этот статический (общедоступный) метод имеет в качестве первого параметра объект класса. Таким образом, вы можете называть его повсюду.

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);
    }
}