开发者

How can I override a virtual method, but still invoke the base class version in C#

I have a simple class hierarchy where I have a virtual method that is overriden. But开发者_C百科 at certain callsites I want to call the base class version of this method rather than the virtual method.

For example:

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

public class B : A {
    public override void Foo() {...}
}

public class Program {
    public void SomeMethod()
    {
       ...

       //  ListofA is type IEnumerable<A>
       foreach (var item in ListofA)
       {
           // I want this to call A.Foo(), rather than B.Foo()
           // But everything I've tried, which has really just been casting, has resulted in B.Foo()
           item.Foo();
       }
    }
}


You can't on an override. Overrides replace the original (from the standpoint of the caller). An overridden method may call the base, but you can't externally.


@James is right. To build on his answer, since you can call the base version from the overridden one, you could send some kind of a flag into the method to tell it whether to execute its own implementation or the overridden one. Something like this:

public override void Foo(bool useBaseImplementation)
{
    if(useBaseImplementation)
    {
        base.Foo(useBaseImplementation);
    }
    else
    {
        //other stuff here
    }
}

In order for it to work, you'd have to have the flag as a parameter for the base one as well, but you could just ignore it there. Not elegant, maybe downright ugly, but does what you're looking for.


If this is the case then what you want isn't actually an override; you should rethink your design. If instead of override you use new in the redefinition the method won't be polymorphic, but again, this is highly indicative of a flawed design. You would also need foreach (A item in ListofA)


I don't like my solution, beacause it sorta uglifies abstration, but maybe you could do the following:

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

public class B : A {
  public override void Foo() {...}
  public override void parentFoo(){
    base.Foo();
  }
}

public class Program {
  public void SomeMethod(){
    ...

     //  ListofA is type IEnumerable<A>
     foreach (var item in ListofA){
       item.Foo(); //calls B.Foo()
       item.parentFoo(); //calls B.parentFoo() == A.Foo()
     }
  }
}


If var item = new A(), it will call A.Foo().


You can call base implementation using the base keyword INSIDE the class, but if You are trying to call it from the other class I am pretty sure You are violating a Liskov Substitution Principle in Your code, as Any subclass shoudl provide such an implementation to virutal methods to be completely substitutable for superclass. Revisit YOUR design.


You can achieve that with using new rather than override. It is very well explained here: http://msdn.microsoft.com/en-us/library/ms173153%28v=vs.80%29.aspx


One possible workaround is not to make the method virtual, but replace it using the new keyword:

   class Program
{
    static void Main(string[] args)
    {
        List<A> list = new List<A>
        {
            new B(),
            new B(),
            new B(),
            new B()
        };

        foreach (A a in list)
        {
            a.Foo();
        }

        foreach (B b in list)
        {
            b.Foo();
        }

        Console.ReadLine();
    }
}

public class A
{
    public void Foo()
    {
        Console.WriteLine("Base");
    }
}

public class B : A
{
    public new void Foo()
    {
        Console.WriteLine("Derived");
    }
}

This will only call the B.Foo() implementation if the reference you use is of type B. I wouldn't encourage you to do this, since I've never came accross a situation where the new keyword made sense.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜