The Template Method pattern gone wrong (or how to stop your overridden methods getting called)

The definition of the “Template Method pattern” may or may not be familiar to you, but the following bit of code sure will:

public abstract class BroadcasterBase 
{ 
    public void SendMessage(Message msg) 
    { 
        // Perform some validation and pre-processing on msg 
        base.SendMessageInternal(msg); 
    } 

    protected virtual void SendMessageInternal(msg)
    {
        // Some default behaviour
    }
}

public class NetworkBroadcaster : BroadcasterBase
{
    protected override void SendMessageInternal(Message msg) 
    {
        // Send the message, now that it has been validated and all pre-processing is complete
    }
}

For the pedants amongst us (which includes me), the Template Method pattern can be defined as:

A template method defines the program skeleton of an algorithm. One or more of the algorithm steps can be overridden by subclasses to allow differing behaviours while ensuring that the overarching algorithm is still followed.

Now this works well until it starts becoming over-engineered and we start having more than one base class. 

public abstract class BroadcasterBase 
{ 
    protected virtual void SendMessageInternal(msg)
    {
        // Some default behaviour
    }
}

public abstract class ValidatingBroadcaster : BroadcasterBase
{
    public void SendMessage(Message msg) 
    { 
        // Perform some validation and pre-processing on msg 
        base.SendMessageInternal(msg); 
    } 
}

public class NetworkBroadcaster : ValidatingBroadcaster
{
    protected override void SendMessageInternal(Message msg) 
    {
        // Send the message, now that it has been validated and all pre-processing is complete
    }
}

And at this point it’s actually broken!  The code inside NetworkBroadcaster will no longer get executed.  This is actually down to one very small bit of code … the use of the “base” keyword in the ValidatingBroadcaster.  This actually makes the call non-virtual and binds it to the specific class, in this case BroadcasterBase.SendMessageInternal.  Eric Lippert puts it nicely:

a base call is a non-virtual call to the nearest method on any base class, based entirely on information known at compile time.

I ran into this problem with the Microsoft Prism framework when extending the eventing mechanism.  Specifically I wanted to derive from CompositePresentationEvent and override the event publication mechanisms.  This particular problem prevented me from doing that.

There are probably two important lessons from this:

  1. Don’t go blithely putting “base.” in front of methods calls, e.g. because something like StyleCop thinks you should
  2. Just because you have a base class with some overridable methods, don’t assume they will get called
June 27 2011
blog comments powered by Disqus