DarioSantarelli.Blog(this);

C# dynamic dispatch and class inheritance

Posted by dariosantarelli on December 8, 2012

I believe dynamic dispatch is a very cool feature of C# 4.0. It was designed to simplify interop between statically typed C# and dynamically typed languages or COM components by deferring method resolution at runtime, dynamically applying the same overload selection logic that the C# compiler would normally use at compile time. This feature is known as single/multiple dispatch. A common usage of this technique can be found in many implementations of the visitor pattern. Maybe you have already read something like this:

public class MessageHandler
{
    public void HandleMessage(Message message)
    {
        ProcessMessage((dynamic)message);
    }
    protected void ProcessMessage(MessageA messageA)
    {
        Console.WriteLine("MessageA processed");
    }

    protected void ProcessMessage(MessageB messageB)
    {
        Console.WriteLine("MessageB processed");
    }
}

This code works great when you don’t know the exact type beforehand and you don’t want to use a big switch statement. If you use dynamic dispatch within the same class everything should work as expected. So, if you execute the following lines of code..

var messageHandler = new MessageHandler();
messageHandler.HandleMessage(new MessageA());
messageHandler.HandleMessage(new MessageB());

…the console output would be the following:

MessageA processed
MessageB processed

OK, but what happens if you introduce a class derived from MessageHandler in order to separate message handling?

The problem

Let’s suppose to have an DefaultMessageHandler that holds the fallback message handling method and a DerivedMessageHandler which holds methods for some specific messages.

public abstract class Message { }
public class MessageA : Message { }
public class MessageB : Message { }
public class MessageC : Message { }

public class DefaultMessageHandler
{
    public void HandleMessage(Message message)
    {
        ProcessMessage((dynamic)message);
    }

    protected void ProcessMessage(Message message)
    {
        Console.WriteLine("Message processed");
    }

    protected void ProcessMessage(MessageA messageA)
    {
        Console.WriteLine("MessageA processed");
    }
}

public class DerivedMessageHandler : DefaultMessageHandler
{
    protected void ProcessMessage(MessageB messageB)
    {
        Console.WriteLine("MessageB processed");
    }

    protected void ProcessMessage(MessageC messageC)
    {
        Console.WriteLine("MessageC processed");
    }
}

When we try to execute the following lines of code…

var messageHandler = new DerivedMessageHandler();
messageHandler.HandleMessage(new MessageA());
messageHandler.HandleMessage(new MessageB());
messageHandler.HandleMessage(new MessageC());

…the console output is…

MessageA processed
Message processed
Message processed

The problem here is that every call to the ProcessMessage method via dynamic dispatch is linked to the only implementation of the method that is found in the DefaultMessageHandler class, and the ones in the derived classes will never be executed. At first glance, this behaviour could be not so easy to expect.

A simple solution

In order for our code to work as expected we could just override the HandleMessage method in the DerivedMessageHandler class, leaving it exactly the same as the one defined in the base class. As alternative, we could completely move the HandleMessage method to derived classes.

public class DefaultMessageHandler
{
    public virtual void HandleMessage(Message message)
    {
        ProcessMessage((dynamic)message);
    }

    protected void ProcessMessage(Message message)
    {
        Console.WriteLine("Message processed");
    }

    protected void ProcessMessage(MessageA messageA)
    {
        Console.WriteLine("MessageA processed");
    }
}

public class DerivedMessageHandler : DefaultMessageHandler
{
    public override void HandleMessage(Message message)
    {
        ProcessMessage((dynamic)message);
    }

    protected void ProcessMessage(MessageB messageB)
    {
        Console.WriteLine("MessageB processed");
    }

    protected void ProcessMessage(MessageC messageC)
    {
        Console.WriteLine("MessageC processed");
    }
}

Now, if we try to handle specific messages…

var messageHandler = new DerivedMessageHandler();
messageHandler.HandleMessage(new MessageA());
messageHandler.HandleMessage(new MessageB());
messageHandler.HandleMessage(new MessageC());
messageHandler.HandleMessage(new MessageD());

…everything works as expected and the console output is

MessageA processed
MessageB processed
MessageC processed
Message processed // fallback for MessageD

Please note that the fallback overload of the ProcessMessage method has been invoked for MessageD because a specific overload has not been dinamically found by the runtime binder.

About these ads

One Response to “C# dynamic dispatch and class inheritance”

  1. Particulary in applications with remoting arch. We can easily this structures,thank you for this post

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: