如何调用base.base.method()?

// Cannot change source code class Base { public virtual void Say() { Console.WriteLine("Called from Base."); } } // Cannot change source code class Derived : Base { public override void Say() { Console.WriteLine("Called from Derived."); base.Say(); } } class SpecialDerived : Derived { public override void Say() { Console.WriteLine("Called from Special Derived."); base.Say(); } } class Program { static void Main(string[] args) { SpecialDerived sd = new SpecialDerived(); sd.Say(); } } 

结果是:

 Called from Special Derived. Called from Derived. /* this is not expected */ Called from Base. 

我怎样才能重写SpecialDerived类,以便中间类“Derived”的方法不被调用?

更新:我想从Derived而不是Baseinheritance的原因是Derived类包含了很多其他的实现。 由于我不能在这里做base.base.method() ,我想最好的办法是做下面的事情?

//无法更改源代码

 class Derived : Base { public override void Say() { CustomSay(); base.Say(); } protected virtual void CustomSay() { Console.WriteLine("Called from Derived."); } } class SpecialDerived : Derived { /* public override void Say() { Console.WriteLine("Called from Special Derived."); base.Say(); } */ protected override void CustomSay() { Console.WriteLine("Called from Special Derived."); } } 

这是一个糟糕的编程习惯,在C#中是不允许的。 这是一个糟糕的编程习惯,因为

  • macros基的细节是基地的实施细节; 你不应该依赖他们。 基类在macros基上提供抽象; 你应该使用这个抽象,而不是build立一个旁路来避免它。

  • 你从你的基础派生,因为你喜欢它的作用,并希望重用和扩展它。 如果你不喜欢它所做的事情,想要解决它而不是处理它,那么你为什么首先从中得出结论呢? 如果这是你想要使用和扩展的function,自己从macros基衍生而来。

  • 为了安全性或语义一致性的目的,这个基地可能需要一定的不variables,这些不variables由基地如何使用这个基地的方法来维护。 允许基类的派生类跳过维护这些不variables的代码可能会将基类置于不一致的损坏状态。

这里只是想补充一点,因为人们在很多时候仍然会回到这个问题上。 当然这是不好的做法,但仍然有可能(原则上)做作者想要的:

 class SpecialDerived : Derived { public override void Say() { Console.WriteLine("Called from Special Derived."); var ptr = typeof(Base).GetMethod("Say").MethodHandle.GetFunctionPointer(); var baseSay = (Action)Activator.CreateInstance(typeof(Action), this, ptr); baseSay(); } } 

你不能从C#。 从IL,这实际上是支持的。 你可以对任何一个父类进行非虚函数调用,但请不要。 🙂

答案(我知道不是你要找的)是:

 class SpecialDerived : Base { public override void Say() { Console.WriteLine("Called from Special Derived."); base.Say(); } } 

事实是,你只能与你inheritance的class级直接互动。 把这个类想象成一个层 – 按照它的派生类的要求,尽可能地提供它或者它的父代的function。

编辑:

你的编辑工作,但我想我会使用这样的事情:

 class Derived : Base { protected bool _useBaseSay = false; public override void Say() { if(this._useBaseSay) base.Say(); else Console.WriteLine("Called from Derived"); } } 

当然,在一个真正的实现中,为了扩展性和可维护性,你可以做更多的事情。

 class Derived : Base { protected enum Mode { Standard, BaseFunctionality, Verbose //etc } protected Mode Mode { get; set; } public override void Say() { if(this.Mode == Mode.BaseFunctionality) base.Say(); else Console.WriteLine("Called from Derived"); } } 

那么派生类可以适当地控制父母的状态。

为什么不简单地将子类转换为特定的父类,然后调用具体的实现呢? 这是一种特殊情况,应该使用特殊情况解决scheme。 虽然你将不得不在儿童方法中使用new关键字。

 public class SuperBase { public string Speak() { return "Blah in SuperBase"; } } public class Base : SuperBase { public new string Speak() { return "Blah in Base"; } } public class Child : Base { public new string Speak() { return "Blah in Child"; } } public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); Child childObj = new Child(); Console.WriteLine(childObj.Speak()); // casting the child to parent first and then calling Speak() Console.WriteLine((childObj as Base).Speak()); Console.WriteLine((childObj as SuperBase).Speak()); } } 

你也可以在一级派生类中做一个简单的函数,调用macros基函数

在你没有访问派生类的源的情况下,但需要除了当前方法的派生类的所有来源,那么我build议你也应该做一个派生类,并调用派生类的实现。

这里是一个例子:

 //No access to the source of the following classes public class Base { public virtual void method1(){ Console.WriteLine("In Base");} } public class Derived : Base { public override void method1(){ Console.WriteLine("In Derived");} public void method2(){ Console.WriteLine("Some important method in Derived");} } //Here should go your classes //First do your own derived class public class MyDerived : Base { } //Then derive from the derived class //and call the bass class implementation via your derived class public class specialDerived : Derived { public override void method1() { MyDerived md = new MyDerived(); //This is actually the base.base class implementation MyDerived.method1(); } } 
 public class A { public int i = 0; internal virtual void test() { Console.WriteLine("A test"); } } public class B : A { public new int i = 1; public new void test() { Console.WriteLine("B test"); } } public class C : B { public new int i = 2; public new void test() { Console.WriteLine("C test - "); (this as A).test(); } } 

我的2c是为了实现你需要在工具包类中调用的function,并从你需要的任何地方调用:

 // Util.cs static class Util { static void DoSomething( FooBase foo ) {} } // FooBase.cs class FooBase { virtual void Do() { Util.DoSomething( this ); } } // FooDerived.cs class FooDerived : FooBase { override void Do() { ... } } // FooDerived2.cs class FooDerived2 : FooDerived { override void Do() { Util.DoSomething( this ); } } 

这确实需要一些想法来访问权限,您可能需要添加一些internal访问器方法来实现function。

从以前的post可以看出,人们可以争辩说,如果需要规避class级function,那么class级架构就会出现问题。 这可能是事实,但是不能总是在一个大的成熟的项目上重组或重构阶级结构。 不同级别的变更pipe理可能是一个问题,但是保持现有function在重构之后运行并不总是一件微不足道的任务,特别是在时间限制的情况下。 在一个成熟的项目中,在代码重组之后,保持各种回归testing不被传递是一件非常有意义的事情。 出现的往往是模糊的“古怪”。 在某些情况下,我们有类似的问题,inheritance的function不应该执行(或者应该执行其他操作)。 我们下面的方法是把需要排除的基本代码放在一个单独的虚拟函数中。 这个函数然后可以在派生类中被覆盖,并且排除或改变function。 在这个例子中,可以防止在派生类中输出“文本2”。

 public class Base { public virtual void Foo() { Console.WriteLine("Hello from Base"); } } public class Derived : Base { public override void Foo() { base.Foo(); Console.WriteLine("Text 1"); WriteText2Func(); Console.WriteLine("Text 3"); } protected virtual void WriteText2Func() { Console.WriteLine("Text 2"); } } public class Special : Derived { public override void WriteText2Func() { //WriteText2Func will write nothing when //method Foo is called from class Special. //Also it can be modified to do something else. } } 

如果要访问基类数据,则必须使用“this”关键字,或者使用此关键字作为类的参考。

 namespace thiskeyword { class Program { static void Main(string[] args) { I i = new I(); int res = i.m1(); Console.WriteLine(res); Console.ReadLine(); } } public class E { new public int x = 3; } public class F:E { new public int x = 5; } public class G:F { new public int x = 50; } public class H:G { new public int x = 20; } public class I:H { new public int x = 30; public int m1() { // (this as <classname >) will use for accessing data to base class int z = (this as I).x + base.x + (this as G).x + (this as F).x + (this as E).x; // base.x refer to H return z; } } }