我怎样才能调用被重载的虚拟方法的“基础实现”?
给定下面的代码,有没有办法可以调用类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 AX somehow, not BX.. }
使用C#语言结构,不能从A
或B
的范围之外明确调用基本函数。 如果你确实需要这样做的话,那么你的devise就有一个缺陷 – 即这个函数不应该是虚拟的,或者一部分基本函数应该被提取到一个单独的非虚函数中。
你可以从BX 里面调用AX
class B : A { override void X() { base.X(); Console.WriteLine("y"); } }
但那是别的。
正如Sasha Truf在这个答案中指出的,你可以通过IL来做到这一点。 你也可以通过反思来完成它,正如评论中指出的那样。
你不能用C#来完成,但你可以编辑MSIL。
你的Main方法的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更改为call
L_0008: call instance void MsilEditing.A::X()
你可以做到这一点,但不是在你指定的地方。 在B
的上下文中,你可以通过调用base.X()
来调用AX()
base.X()
。
你不能,而你不应该。 这就是多态的目的,所以每个对象都有自己的方式来做一些“基础”的事情。
我现在知道这是历史问题。 但对于其他谷歌:你可以写这样的事情。 但是这需要在基类中进行更改,使其对外部库无用。
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 AX somehow, not BX.. 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(); aX(); // returns Derived 1 bX(); // returns Base cX(); // returns Derived 2
在这里看小提琴