131

Given the following code, is there a way I can call class A's version of method X?

class A
{
  virtual void X() { Console.WriteLine("x"); }
}

class B : A
{
  override void X() { Console.WriteLine("y"); }
}

class Program
{
  static void Main()
  {
    A b = new B();
    // Call A.X somehow, not B.X...
  }
Matthew Lock
  • 13,144
  • 12
  • 92
  • 130
mackenir
  • 10,801
  • 16
  • 68
  • 100

6 Answers6

175

Using the C# language constructs, you cannot explicitly call the base function from outside the scope of A or B. If you really need to do that, then there is a flaw in your design - i.e. that function shouldn't be virtual to begin with, or part of the base function should be extracted to a separate non-virtual function.

You can from inside B.X however call A.X

class B : A
{
  override void X() { 
    base.X();
    Console.WriteLine("y"); 
  }
}

But that's something else.

As Sasha Truf points out in this answer, you can do it through IL. You can probably also accomplish it through reflection, as mhand points out in the comments.

Pete
  • 12,206
  • 8
  • 54
  • 70
  • Calling A.X() from inside B is the only situation I can even see you needing to call it once overriden. Say you had a copy method with base class members, then override it to add copy functionality for new members and call base.copy() inside so all gets copied. – steviesama Jun 29 '15 at 02:20
  • Interesting,I would have thought it could be accomplished via reflection? – mhand Aug 04 '15 at 22:16
  • When writing tests, its not unusual to want to modify behavior through polymorphic tricks. As such, needing to call base methods from within a overridden method does not necessarily indicate bad design -- it might indicate design that is hard to test. I came across your answer exactly due to such needs. – Pétur Ingi Egilsson Jun 22 '17 at 05:50
  • @PéturIngiEgilsson - When you write, "call base methods from within a overridden method", I think there is a difference between what you write there, and what the OP, that was calling the base method from *outside* the derived class. As I understood your comment, you are talking about calling the method from *inside* the derived class, which is what I point out is possible. – Pete Jun 22 '17 at 07:15
  • @Pete I stand corrected! – Pétur Ingi Egilsson Jun 22 '17 at 07:56
17

You can't do it by C#, but you can edit MSIL.

IL code of your Main method:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] class MsilEditing.A a)
    L_0000: nop 
    L_0001: newobj instance void MsilEditing.B::.ctor()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: callvirt instance void MsilEditing.A::X()
    L_000d: nop 
    L_000e: ret 
}

You should change opcode in L_0008 from callvirt to call

L_0008: call instance void MsilEditing.A::X()
Sasha Truf
  • 535
  • 5
  • 19
14

It's impossible if the method is declared in the derived class as overrides. to do that, the method in the derived class should be declared as new:

public class Base {

    public virtual string X() {
        return "Base";
    }
}
public class Derived1 : Base
{
    public new string X()
    {
        return "Derived 1";
    }
}

public class Derived2 : Base 
{
    public override string X() {
        return "Derived 2";
    }
}

Derived1 a = new Derived1();
Base b = new Derived1();
Base c = new Derived2();
a.X(); // returns Derived 1
b.X(); // returns Base
c.X(); // returns Derived 2

See fiddle here

Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • 3
    I feel this should be the answer to this problem. If you change the way you are "overriding" the method to making it a new one with the same signature, then everything else should work fine. – Javier Rapoport Mar 24 '21 at 17:58
10

You can do it, but not at the point you've specified. Within the context of B, you may invoke A.X() by calling base.X().

John Feminella
  • 303,634
  • 46
  • 339
  • 357
9

You can't, and you shouldn't. That's what polymorphism is for, so that each object has its own way of doing some "base" things.

Jorge Córdoba
  • 51,063
  • 11
  • 80
  • 130
6

I konow it's history question now. But for other googlers: you could write something like this. But this requires change in base class what makes it useless with external libraries.

class A
{
  void protoX() { Console.WriteLine("x"); }
  virtual void X() { protoX(); }
}

class B : A
{
  override void X() { Console.WriteLine("y"); }
}

class Program
{
  static void Main()
  {
    A b = new B();
    // Call A.X somehow, not B.X...
    b.protoX();


  }
lkuder
  • 69
  • 1
  • 1