C# Dynamic and Multiple Dispatch

I crashed Mads' C# Tech Chat at Tech Ed EMEA in Barcelona on the grounds that the dynamic world has monkey-patched C#.  It was fun, and I had the opportunity to answer a few dynamic/DLR-related questions that Mads was probably more capable of handling than I was.

One question that I choked on was whether or not this new language feature could be used to enable multiple dispatch from within C#.  My gut feeling was that the answer was “yes”, but I couldn’t quite justify the answer so I hedged and hemmed and hawed and didn’t provide anything remotely like a satisfactory answer for the guy asking the question.

But now that I’ve had the benefit of a good night’s rest, the answer is blindingly obvious: yes, and here’s the evidence in some C# 4 sample code:

 public class A {
 }
  
 public class B : A {
 }
  
 public class C : B {
 }
  
 public class D {
 }
  
 public class E : D {
 }
  
 public class Test {
     public void Multi(D d, A a) { System.Console.WriteLine("DA"); }
     public void Multi(D d, B b) { System.Console.WriteLine("DB"); }
     public void Multi(D d, C c) { System.Console.WriteLine("DC"); }
     public void Multi(E e, A a) { System.Console.WriteLine("EA"); }
     public void Multi(E e, B b) { System.Console.WriteLine("EB"); }
     public void Multi(E e, C c) { System.Console.WriteLine("EC"); }
  
     public static void Main() {
         Test test = new Test();
         A a = new A();
         A b = new B();
         A c = new C();
         D d = new D();
         D e = new E();
         test.Multi(d, a);
         test.Multi(e, b);
         test.Multi(e, c);
         test.Multi((dynamic)d, (dynamic)a);
         test.Multi((dynamic)e, (dynamic)b);
         test.Multi((dynamic)e, (dynamic)c);
     }
 }

This produces the output

 DA
DA
DA
DA
EB
EC

Why does it work?

When you use dynamic, you’re telling the C# binder to ignore anything that it knows about the type at compile time and to instead determine dispatch based on the actual type at runtime.  The statically-bound method calls, by contrast, performs a dispatch based solely on the declared type.

So there you have it – one more use for dynamic: painless implementation of multiple dispatch.

(Thanks to Lucian Wischik for pointing out a flaw with the original version of this post.)