C#: Any way to skip over one of the base calls in

2020-04-02 08:54发布

class GrandParent
{
    public virtual void Foo() { ... }
}

class Parent : GrandParent
{
    public override void Foo()
    {
       base.Foo();

       //Do additional work
    }
}

class Child : Parent
{
    public override void Foo()
    {
        //How to skip Parent.Foo and just get to the GrandParent.Foo base?

        //Do additional work
    }
}

As the code above shows, how can I have the Child.Foo() make a call into GrandParent.Foo() instead of going into Parent.Foo()? base.Foo() takes me to the Parent class first.

6条回答
相关推荐>>
2楼-- · 2020-04-02 09:23

I think there is something wrong with your design here. Essentially, you want to "break" the rules of polymorphism. You are saying Child should derive from Parent but want to conveniently skip the implementation in it's parent.

Re-think your design.

查看更多
ゆ 、 Hurt°
3楼-- · 2020-04-02 09:23

We had exactly this scenario on a large project where the derived methods were called from various locations. Due to change management and QA scripts not to be broken, among other constraints, "drastic" refactoring and class re-structuring are not always possible on a large mature project. Also we did not want to override the method and exclude all base functionality. Most solutions seen elsewhere, looked a bit clumsy, but the solution from Josh Jordan on How to call base.base was quite useful.

However we followed the approach below (which I see now is very similar to what Dan Abramov propose).

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.
    }
}   

查看更多
太酷不给撩
4楼-- · 2020-04-02 09:29

If you have control of the code, the simplest way is to create a protected method in Parent class that only call base.Foo() and your child class Foo implementation call that method explicitly

查看更多
我只想做你的唯一
5楼-- · 2020-04-02 09:32

Your design is wrong if you need this.
Instead, put the per-class logic in DoFoo and don't call base.DoFoo when you don't need to.

class GrandParent
{
    public void Foo()
    {
        // base logic that should always run here:
        // ...

        this.DoFoo(); // call derived logic
    }

    protected virtual void DoFoo() { }
}

class Parent : GrandParent
{
    protected override void DoFoo()
    {    
       // Do additional work (no need to call base.DoFoo)
    }
}

class Child : Parent
{
    protected override void DoFoo()
    {  
        // Do additional work (no need to call base.DoFoo)
    }
}
查看更多
▲ chillily
6楼-- · 2020-04-02 09:34

No, this isn't possible. Imagine how crazy things would be if this was possible.

If you want something specific skipped in the Child case, consider reworking your design to better represent what you need (e.g. maybe you need to override something else in the Child class, too). Or, you could provide another Foo() in the Parent class that doesn't do anything except call its base.Foo().

查看更多
Emotional °昔
7楼-- · 2020-04-02 09:35

No. It wouldn't be reliable anyway. You, as the implementer of your class, get to choose your immediate base class. But who is to say that a later release of Parent might not inherit from ParentBase, that in turn inherits from GrandParent? So long as Parent is still implementing the correct contract, this should not cause any issues for those classes inheriting from Parent.

查看更多
登录 后发表回答