In C#, there are two ways you can pro­vide an alter­na­tive imple­men­ta­tion of an inher­ited method:

Over­ride a vir­tual method

Unlike Java where every method can be over­rid­den by default unless marked with the final key­word, C# employs a safer, opt-in sys­tem where meth­ods can­not be over­rid­den unless marked with the vir­tual keyword.

A vir­tual method defined in the base class can be over­rid­den in a derived class by defin­ing a method with the same sig­na­ture and mark­ing it with the over­ride keyword.

Hid­ing a base method

With­out mark­ing a method in the base class with the vir­tual key­word it is still pos­si­ble (albeit not rec­om­mended) to pro­vide an over­ride by ‘hid­ing’ the method defined in the base class. All you need to do is to declare the same method sig­na­ture in the derived class.

Philo­soph­i­cal Difference

Under nor­mal cir­cum­stances, hid­ing a base method is a code smell. It unnec­es­sar­ily com­pli­cates the rela­tion­ship between the base and derived class as it’s not imme­di­ately clear which method is invoked when you call derived.Foo() if Foo() is declared in both the base and derived class.

To lessen this con­fu­sion, you should use the new key­word when­ever you absolutely have to hide a method in the base class:

public class BaseClass
{
    public void Foo() { … }
}

public class DerivedClass
{
    public new void Foo() { … }
}

This way, when some­one looks at your code it at least offers some indi­ca­tion that Foo() is an over­ride and more impor­tantly, it makes a state­ment of your inten­tion to hide the Foo() method in the base class (as opposed to it look­ing like a mistake).

Over­rid­ing a vir­tual method on the other hand, is very much part and par­cel of object ori­ented design, and an inte­gral part of the Tem­plate pat­tern (one of my favourites :-P) to allow vari­a­tions in the behav­iour of the con­crete classes. It allows you to make a clear state­ment both in the base and derived class that a method is intended and some­times expected to be overridden.

Seman­tic Difference

Seman­ti­cally there’s a very sub­tle dif­fer­ence between the two approaches because the tim­ing in which the method to invoke is deter­mined dif­fers between the two:

  • When you hide a base method the method is resolved at com­pile time – which method is invoked at run­time is pre­de­ter­mined based on what they look like at com­pile time and baked into the com­piled dll.
  • When you over­ride a vir­tual method the method is resolved at run­time – the CLR deter­mines which method to invoke by look­ing up a ‘call table’ and find the near­est over­ride of the method.

Here’s a sce­nario where you will notice the difference:

Imag­ine you have two classes TypeA and TypeB, located in Assem­blyA and Assem­blyB respec­tively:

public class TypeA // in AssemblyA.dll
{
    public void Foo()
    {
        Console.Write("TypeA.Foo()");
    }

    public virtual void Boo()
    {
        Console.Write("TypeA.Boo()");
    }
}

public class TypeB : TypeA // in AssemblyB.dll
{
}

In my appli­ca­tion which uses both libraries, I have these lines of code:

var typeb = new TypeB();
typeb.Foo();
Console.WriteLine();
typeb.Boo();

And no prizes for guess­ing the out­put of this code:

image

Now, sup­pose I decided at a later date that I wish to over­ride Foo() and Boo() in TypeB:

public class TypeB : TypeA // in AssemblyB.dll
{
    public void Foo()
    {
        Console.Write("TypeB.Foo()");
        base.Foo();
    }

    public override void Boo()
    {
        Console.Write("TypeB.Boo()");
        base.Boo();
    }
}

See­ing as noth­ing else have changed, so I recom­pile only Assem­blyB and dis­trib­ute the new dll, what do you think the out­put is when I rerun my appli­ca­tion? Well, a lit­tle surprisingly:

image

Ref­er­ences:

Eric Lippert’s blog post: putting a base in the middle

Share

One Response to “Hiding a base method vs Overriding a virtual method”

  1. Great story and example

Leave a Reply