C# 如何调用重写的虚拟方法的“基本实现”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1334254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:16:18  来源:igfitidea点击:

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

c#oop

提问by mackenir

Given the following code, is there a way I can call class A's version of method X?

鉴于以下代码,有没有办法调用 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...
  }

采纳答案by Pete

Using the C# language constructs, you cannot explicitly call the base function from outsidethe scope of Aor B. If you really need to do that, then there is a flaw in your design - i.e. that function shouldn't be virtual to begin with, or part of the base function should be extracted to a separate non-virtual function.

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

You can from insideB.X however call A.X

您可以从BX内部调用 AX

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

But that's something else.

但那是另一回事。

As Sasha Truf points out in this answer, you can do it through IL. You can probably also accomplish it through reflection, as mhand points out in the comments.

正如 Sasha Truf 在这个答案中指出的那样,您可以通过 IL 来完成。正如 mhand 在评论中指出的那样,您可能也可以通过反射来完成它。

回答by Jorge Córdoba

You can't, and you shouldn't. That's what polymorphism is for, so that each object has its own way of doing some "base" things.

你不能,也不应该。这就是多态性的用途,因此每个对象都有自己的方式来做一些“基本”的事情。

回答by John Feminella

You can do it, but not at the point you've specified. Within the context of B, you may invoke A.X()by calling base.X().

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

回答by lkuder

I konow it's history question now. But for other googlers: you could write something like this. But this requires change in base class what makes it useless with external libraries.

我知道现在是历史问题。但对于其他谷歌员工:你可以写这样的东西。但这需要改变基类,这使得它对外部库毫无用处。

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


  }

回答by Sasha Truf

You can't do it by C#, but you can edit MSIL.

你不能用 C# 来做,但你可以编辑 MSIL。

IL code of your Mainmethod:

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 
}

You should change opcode in L_0008 from callvirtto call

您应该将 L_0008 中的操作码从callvirt 更改call

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

回答by Zohar Peled

It's impossible if the method is declared in the derived class as overrides. to do that, the method in the derived class should be declared as new:

如果该方法在派生类中声明为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

See fiddle here

在这里看到小提琴