Как я могу назвать "базовую реализацию" переопределенного виртуального метода?
Учитывая следующий код, существует ли способ, которым я могу назвать класс A методом X?
class A
{
virtual void X() { Console.WriteLine("x"); }
}
class B : A
{
override void X() { Console.WriteLine("y"); }
}
class Program
{
static void Main()
{
A b = new B();
// Call A.X somehow, not B.X...
}
Ответы
Ответ 1
Используя конструкторы языка С#, вы не можете явно вызвать базовую функцию извне области A
или B
. Если вам действительно нужно это сделать, тогда есть недостаток в вашем дизайне - то есть эта функция не должна быть виртуальной для начала, или часть базовой функции должна быть извлечена в отдельную не виртуальную функцию.
Вы можете изнутри B.X однако вызвать A.X
class B : A
{
override void X() {
base.X();
Console.WriteLine("y");
}
}
Но что-то еще.
Как говорит Саша Труф в этом ответе, вы можете сделать это через IL.
Возможно, вы также можете сделать это через отражение, как указывает мэндер в комментариях.
Ответ 2
Вы не можете сделать это с помощью С#, но вы можете редактировать MSIL.
IL-код вашего метода Основной:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] class MsilEditing.A a)
L_0000: nop
L_0001: newobj instance void MsilEditing.B::.ctor()
L_0006: stloc.0
L_0007: ldloc.0
L_0008: callvirt instance void MsilEditing.A::X()
L_000d: nop
L_000e: ret
}
Вы должны изменить код операции в L_0008 с callvirt на вызов
L_0008: call instance void MsilEditing.A::X()
Ответ 3
Вы не можете, и не должны. Для чего нужен полиморфизм, так что каждый объект имеет свой собственный способ сделать некоторые "базовые" вещи.
Ответ 4
Вы можете сделать это, но не в том месте, которое вы указали. В контексте B
вы можете вызвать A.X()
, вызвав base.X()
.
Ответ 5
Теперь я задаю этот вопрос истории. Но для других гуглеров: вы могли бы написать что-то вроде этого. Но это требует изменения базового класса, что делает его бесполезным с внешними библиотеками.
class A
{
void protoX() { Console.WriteLine("x"); }
virtual void X() { protoX(); }
}
class B : A
{
override void X() { Console.WriteLine("y"); }
}
class Program
{
static void Main()
{
A b = new B();
// Call A.X somehow, not B.X...
b.protoX();
}
Ответ 6
Невозможно, если метод объявлен в производном классе как overrides
. для этого метод в производном классе должен быть объявлен как new
:
public class Base {
public virtual string X() {
return "Base";
}
}
public class Derived1 : Base
{
public new string X()
{
return "Derived 1";
}
}
public class Derived2 : Base
{
public override string X() {
return "Derived 2";
}
}
Derived1 a = new Derived1();
Base b = new Derived1();
Base c = new Derived2();
a.X(); // returns Derived 1
b.X(); // returns Base
c.X(); // returns Derived 2
Смотрите здесь скрипку