简体   繁体   English

从子类成员调用基类成员函数

[英]Call base class member functions from subclass members

public class A
{
    ...
    public virtual void PrintMe() { /* do A */ }
}

public class B : A
{
    ...
    public override void PrintMe() { /* do B */ }
}

public class C : B
{
    ...
    public override void PrintMe() { /* do C */ }

    private void Fun()
    {
        // call C::PrintMe - part one
        PrintMe();

        // call B::PrintMe - part two
        base.PrintMe();

        // call A::PrintMe - part three
        ???
    }
}
  1. Is the code of part two correct? 第二部分的代码正确吗?

  2. How to call A::PrintMe inside C::Fun ? 如何在C::Fun内调用A::PrintMe

Your question 1 will work as expected, it will do B.PrintMe() 您的问题1将按预期工作,它将执行B.PrintMe()

Your question 2 is not quite so simple. 您的问题2并非那么简单。 There is no implicit or explicit way to execute A.PrintMe() . 没有执行A.PrintMe()隐式或显式方法。

The only way I can think to achieve your goal is with the addition of a protected method on A which can be called from C . 我想达到目标的唯一方法是在A上添加可以从C调用的受保护方法。

public class A
{
    protected void BasePrintMe() { Console.WriteLine("A"); }
    public virtual void PrintMe() { BasePrintMe(); }
}

public class B : A { public override void PrintMe() { Console.WriteLine("B"); } }

public class C : B
{
    public override void PrintMe() { Console.WriteLine("C"); }

    public void FunA()
    {
        // call C::PrintMe - part one
        PrintMe();

        // call B::PrintMe - part two
        base.PrintMe();

        // call A
        this.BasePrintMe();

    }

}

output: 输出:

C
B
A

If you want this desired functionality, you can call base.PrintMe() in your B class. 如果需要此功能,可以在B类中调用base.PrintMe()

public class B : A
{
    public override void PrintMe()
    { 
     /* do B */
     base.PrintMe();
    }
}

Otherwise, you can't call the implementation from class A without resorting to something hackish. 否则,您不能不借助某些骇客的东西而从A类调用实现。

You could add a method to each class that would do a base.PrintMe() . 您可以将一个方法添加到每个将执行base.PrintMe() In A, this method would do nothing as it has no base class. 在A中,此方法不执行任何操作,因为它没有基类。

   public class A
   {
      public virtual void PrintMe()
      {
         Debug.WriteLine( "PrintMe: A" );
      }

      public virtual void PrintMyBase()
      {
      }
   }

   public class B : A
   {
      public override void PrintMe()
      {
         Debug.WriteLine( "PrintMe: B" );
      }

      public override void PrintMyBase()
      {
         base.PrintMe();
      }
   }

   public class C : B
   {
      public override void PrintMe()
      {
         Debug.WriteLine( "PrintMe: C" );
      }

      public override void PrintMyBase()
      {
         base.PrintMe();
      }

      private void Fun()
      {
         // call C::PrintMe - part one
         PrintMe();

         // call B::PrintMe - part two
         PrintMyBase();

         // call A::PrintMe - part three
         base.PrintMyBase();
      }
   }

The befit here is that no class has to know anything more than it's base class and we can control what's exposed down the inheritance chain. 这样做的好处是,除了基类之外,没有其他类比其他任何人都知道什么,我们可以控制继承链中暴露的内容。

Hope this helps 希望这可以帮助

There's no language-supported way of doing this, which is a handy hint to suggest that you shouldn't do it . 没有语言支持的方法,这是一个方便的提示,建议您不要这样做

If you find yourself needing this in real-world code then you should really try to re-think your design. 如果您发现自己在实际代码中需要此功能,那么您应该尝试重新考虑您的设计。

Anyway, to answer the question, you can do this using reflection and some custom IL-generation, like so: 无论如何,要回答这个问题,您可以使用反射和一些自定义的IL生成来实现,如下所示:

private void Fun()
{
    // call C::PrintMe - part one
    PrintMe();

    // call B::PrintMe - part two
    base.PrintMe();

    // call A::PrintMe - part three
    MethodInfo mi = this.GetType().GetMethod("PrintMe").GetBaseDefinition();

    var dm = new DynamicMethod("dm", null, new[] { typeof(object) }, this.GetType());

    ILGenerator il = dm.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Call, mi);    // use call rather than callvirt
    il.Emit(OpCodes.Ret);

    var action = (Action<object>)dm.CreateDelegate(typeof(Action<object>));
    action(this);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM