2009-06-17 4 views
28
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()?Как вызвать метод базового класса второго уровня, такой как base.base.GetHashCode()

Редактировать: B сейчас наследует от A.

+3

Возможно, вы имели в виду класс B inherit from class A? – AakashM

+0

@AakashM - хорошее место! Я мысленно вставил его, не заметив, что его нет; Я думаю, мы можем предположить, что это должно быть ... –

+0

он должен. Я добавил его. – usr

ответ

17

(редактировать - неправильно истолковывать вопрос)

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

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

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

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

+0

Похоже, я тоже неправильно понял. Хороший улов. – Welbog

+0

На самом деле, я думал, вы можете использовать отражение, чтобы вызвать определенную версию метода, даже если он виртуальный. – LBushkin

+3

@LBushkin - Я тоже так думал; но когда я попробовал это некоторое время назад (используя пользовательский IL и «call» вместо «callvirt»), CLI отклонил его, сказав, что он может дестабилизировать время выполнения (и это было для тривиального примера). –

13

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

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

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

база хэш-код является: хэш-код 54267293
A в: 1
A исходный хэш-код: 54267293

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

7

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

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

Таким образом, важный код:

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

«довольно просто» не так, как я думал, когда читаю код, но он работает как шарм :-)! –

0

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

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); 
    } 
} 
Смежные вопросы