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
???
}
}
第二部分的代码是否正确?
如何在A::PrintMe
内拨打C::Fun
?
答案 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);
}