关于c#:如何调用重写的虚方法的“基础实现”?

How can I call the 'base implementation' of an overridden virtual method?

本问题已经有最佳答案,请猛点这里访问。

给定以下代码,有没有方法可以调用类A的方法X版本?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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...
  }

使用C语言结构,不能从AB的范围之外显式调用基函数。如果您真的需要这样做,那么您的设计中就存在一个缺陷——即,该函数不应该是从虚拟开始的,或者应该将基本函数的一部分提取到单独的非虚拟函数。

你可以从B.X内部呼叫A.X

1
2
3
4
5
6
7
class B : A
{
  override void X() {
    base.X();
    Console.WriteLine("y");
  }
}

但那是另外一回事。

正如萨沙·特鲁夫在这个答案中指出的那样,你可以通过IL来做到这一点。正如mhand在评论中指出的那样,你也可以通过反思来完成它。


你不能用c来完成,但是你可以编辑msil。

主要方法的IL代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.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

1
L_0008: call instance void MsilEditing.A::X()


你可以这样做,但不是在你指定的地方。在B的上下文中,您可以通过调用base.X()来调用A.X()


你不能,你也不应该。这就是多态性的目的,所以每个对象都有自己的方式来做一些"基础"的事情。


我知道这是历史问题了。但是对于其他谷歌用户:你可以写这样的东西。但这需要在基类中进行更改,这就使得它不能用于外部库。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

在这里看小提琴