Как я могу вызвать "базовую реализацию" переопределенного виртуального метода? [дубликат]



этот вопрос уже есть ответ здесь:




  • Есть ли способ вызвать родительскую версию переопределенного метода? (C# .NET)

    8 ответов



учитывая следующий код, есть ли способ вызвать версию метода X класса A?



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...
}
584   6  

6 ответов:

используя конструкции языка C#, вы не можете явно вызвать базовую функцию из за пределами объем A или B. Если вам действительно нужно это сделать, то в вашем дизайне есть недостаток - т. е. эта функция не должна быть виртуальной для начала, или часть базовой функции должна быть извлечена в отдельную невиртуальную функцию.

вы можете внутри B. X однако вызовите A. X

class B : A
{
  override void X() { 
    base.X();
    Console.WriteLine("y"); 
  }
}

но это уже что-то еще.

как Саша Truf в ответ, вы можете сделать это через IL. Вероятно, вы также можете выполнить это через отражение, как указывает mhand в комментариях.

вы не можете сделать это с помощью C#, но вы можете редактировать 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()

вы не можете, и вы не должны. Вот что полиморфизм, так что каждый объект имеет свой собственный способ делать некоторые "базовые" вещи.

вы можете сделать это, но не в том месте, которое вы указали. В контексте B, вы можете использовать A.X() по телефону base.X().

Я konow это уже вопрос истории. Но для других гуглеров: вы могли бы написать что-то вроде этого. Но это требует изменения в базовом классе, что делает его бесполезным с внешними библиотеками.

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


  }

- Это невозможно, если метод объявлен в производном классе как 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

увидеть скрипку здесь

Comments

    Ничего не найдено.