C# 4: Reflected Dynamics

In Scott Hanselman's blog-entry titled Back to Basics: C# 4 method overloading and dynamic types , Scott talks about method-overloads in C# 4 and the dynamic -keyword.

class Program {
    static void f(Int32 x) { }
    static void f(dynamic x) {}
    static void f(Int32 x, dynamic y) {}
    static void f(dynamic x, Int32 y) {}
    static void f(Int32 x, dynamic y, Int32 z) {}
    static void f(dynamic x, Int32 y, dynamic z) {}
    static void Main(string[] args) {
        f(10); // Works - obvious
        f(10, 10); // Ambiguous - obvious
        f(10, 10, 10); // Ambiguous - not so obvious - since it should be possible to resolve

...the behavior is totally by design:

  • dynamic in method signatures doesn’t come into it: it behaves like System.Object does.
  • Given that, neither of the ternary signatures is better because each fits better than the other on some arguments (Int32 fits 10 better than object does)

The key point here, in bold, because it's significant is: having the type dynamic means "use my runtime type for binding".

It all becomes very clear when Reflector is used on the code. This loosens up some thought-patterns and makes it easier to really understand the dynamic -keyword.

Another way to look at this is with Reflector. This C# code:

static void f(Int32 x, dynamic y, Int32 z) {}

is essentially this, from a method signature point of view:

static void f(int x, \[Dynamic\] object y, int z) {}

and if there was a method that returned dynamic, it'd look like this:

[return: Dynamic]
    private static object GetCalculator() {}