Как вызвать метод базового класса второго уровня, например 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);
}
}