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

时间:2011-08-09 15:40:12

标签: c#

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. 第二部分的代码是否正确?

  2. 如何在A::PrintMe内拨打C::Fun

4 个答案:

答案 0 :(得分:2)

您的问题1将按预期工作,它将执行B.PrintMe()

你的问题2并不那么简单。没有隐式或显式方式来执行A.PrintMe()

我能想到实现目标的唯一方法是在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();

    }

}

输出:

C
B
A

答案 1 :(得分:0)

如果您需要此功能,可以在base.PrintMe()课程中致电B

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

否则,您无法通过类A调用实现而不诉诸于hackish。

答案 2 :(得分:0)

您可以为每个可以执行base.PrintMe()的类添加方法。在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();
      }
   }

这里的装备是,除了它的基类之外,任何类都不需要知道任何东西,我们可以控制继承链中暴露的内容。

希望这有帮助

答案 3 :(得分:-1)

没有语言支持的方式,这是一个方便的暗示,建议你不应该这样做

如果您发现自己需要使用真实代码,那么您应该尝试重新考虑您的设计。

无论如何,要回答这个问题,你可以使用反射和一些自定义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);
}