Multi-methods / Multi-Dispatch / Dynamic dispatch is a mechanism to dispatch a message to the run-time type (if two input parameters are bound to their runtime types then it’s known as double dispatch). Usually compiler keeps a table (known as virtual table or vtable) to know the objects’ dynamically bound methods. Before C# 4.0, this table was constructed in compilation time, but since the introduction of the dynamic keyword the vtable is built in runtime. I wanted to write this post because I found several blogs implementing the “asteroid collides planet” sample, which I think provide little insight.
The following example shows a base interface (IMessageStream) and concrete implementations (classes Message and MessageV2):

    public interface IMessageStream
    {
        void Read();
    }

    public class Message : IMessageStream
    {
        public void Read() { }
    }

    public class MessageV2 : IMessageStream
    {
        public void Read() { }
    }

The class DataContext stores messages into database using the data returned by the interface implementations. More exactly, the DataContext delegates to the input parameter (msgObj) the task of getting the message raw data to be stored. The following code shows the DataContext class with 3 overloads of the SaveMessage method, one per type/subtype:

    public class DataContext
    {
        public void SaveMessage(IMessageStream msgObj)
        {
            Console.WriteLine("Using IMessageStream");
            msgObj.Read();
        }

        public void SaveMessage(Message msgObj)
        {
            Console.WriteLine("Using Message");
            msgObj.Read();
        }

        public void SaveMessage(MessageV2 msgObj)
        {
            Console.WriteLine("Using MessageV2");
            msgObj.Read();
        }
    }

Now consider the following code to inject the IMessageStream dependency in the SaveMessage method:

            dynamic msg = new Message();           //typed at runtime
            IMessageStream msg2 = new Message();   //typed at compile time
            IMessageStream msg3 = new MessageV2(); //typed at compile time
            dynamic msg4 = new MessageV2(); 	   //typed at runtime

            DataContext db = new DataContext();
            db.SaveMessage(msg);    //prints: Using Message
            db.SaveMessage(msg2);   //prints: Using IMessageStream
            db.SaveMessage(msg3);   //prints: Using IMessageStream
            db.SaveMessage(msg4);   //prints: Using MessageV2

Multi-Methods/Multi-Dispatch (or double dispatch if two dynamic input parameters are used) /Dynamic Dispatch allows to select at runtime the specific implementation (for interfaces) or subclass (for classes/abstract classes) to be used. Without dynamic the implementation is selected at compilation time (which is usually a base interface/class). With dynamic the implementation is selected at runtime, so the specific class is selected. This example showed a flavor or abstraction using different data types (subtyping) and different behaviors (polymorphism).

Many authors agree in a single class (e.g. DataContext) with polymorphic methods as the way to use the specific types. I also think you should have a good reason to implement techniques like this (e.g.: replacing a “bad” looking switch block) because it increases the complexity of your design. From a simplistic (kind of) end users’ point of view the dynamic keyword duck types because it says the compiler that an object support any method, then the run-time matches the method signature with the actual type. Bear in mind than dynamic is about deferred binding time and the var keyword is simply a shortcut to avoid writing twice a type, so the following two lines are the same:

 Program myProgram = new Program();
 var myProgram = new Program();

Cheers,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP

Intel Black Belt Software Developer