Pitfalls and Best Practices to prevent them #3: this and base

“I use base to make clear that I am calling a inherited member” – why you shouldn’t.

You all know them: The keywords this and base.

Did you ever think about which of them you should use when you can use both?

Example

class Program
{
    static void Main(string[] args)
    {
        new Baz().Method();
        Console.ReadLine();
    }
}

public class Foo
{
    public virtual string Property
    {
        get
        {
            return "Goodbye Welt";
        }
    }
    public virtual void Method()
    {
        Console.WriteLine(this.Property);
    }
}

public class Sub : Foo
{
    public override void Method()
    {
        Console.WriteLine("I say \"{0}\"", base.Property);
    }
}

public class Baz : Sub
{
    public override string Property
    {
        get
        {
            return "Hello World";
        }
    }
}

What does it do?

We have a class hierarchy here: Foo is the base class and provides two members: The method Method and the property Property (I’ll talk about descriptive names later ;-) ).

Now Sub derives from Foo and overrides Method. As base indicates that a member of the base class (Foo) is called, the author used it to make his purpose clearer.

Baz, again, derives from Sub and returns another value for Property.

Now we expect that if we instantiate Baz and call Method, that there will stand “I say: “Hello World”” on the console.

What does it actually do?

It prints out: “I say: Goodbye world”.

Doku says

Nothing we do not already know:

base (C# Reference)

The base keyword is used to access members of the base class from within a derived class:

- Call a method on the base class that has been overridden by another method.

- Specify which base-class constructor should be called when creating instances of the derived class.

Problem

The real difference between our two keywords is quite simple: While this performs a virtual call, base does not.

We change Sub.Method to the following:

Console.WriteLine("I say \"{0}\"", this.Property);
Console.WriteLine("I say \"{0}\"", base.Property);

Using the Reflector, we see that Sub.Method now generates the following IL-Assembler code:

.method public hidebysig virtual instance void Method() cil managed
{
    .maxstack 8
    L_0000: nop
    L_0001: ldstr "I say \"{0}\""
    L_0006: ldarg.0
    L_0007: callvirt instance string ConsoleApplication1.Foo::get_Property()
    L_000c: call void [mscorlib]System.Console::WriteLine(string, object)
    L_0011: nop
    L_0012: ldstr "I say \"{0}\""
    L_0017: ldarg.0
    L_0018: call instance string ConsoleApplication1.Foo::get_Property()
    L_001d: call void [mscorlib]System.Console::WriteLine(string, object)
    L_0022: nop
    L_0023: ret
}

You see the difference? this results in a callvirt while base results in a simple call (non-virtual).

How to solve?

Replace base with this (or leave it away – but that’s another discussion).

Generalization / Best Practice

As base performs a non-virtual call you should only use it when you want to call the “original” method within an overridden method.

Do not use base in order to make clearer you are calling a method of the base class. Use this instead.

DotNetKicks Image
About these ads

2 Responses to “Pitfalls and Best Practices to prevent them #3: this and base”

  1. Trev Says:

    If you use any tools like StyleCop, they will pick up on this for you and tell you that as you have not overriden a property or method it should be prefixed “this” instead of “base” so you can catch potential bugs like this at design time.

  2. DotNetShoutout Says:

    Pitfalls and Best Practices to prevent them #3: this and base « winSharp’s Blog…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…


Comments are closed.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: