Odd Behavior of C# 4.0 "Dynamic"

Update: Since this behavior hasn’t changed in VS 2010 RC, I have reported the problem to MS on their Connect Site: Dynamic Dispatch in C# doesn’t seem to work in simple case

I’m testing a few things with VS 2010 beta 2, around the “dynamic” keyword in C# 4.0. Mostly good, but there’s a bit of odd behavior – I thought I’d post about it, in case somebody has a comment, and so I don’t forget to test again once I go to the RC again (had it installed the other day, just to find there was no compatible IronPython release and no F# PowerPack either!). So here’s one thing that’s weird. I have two classes:

public class Leaf {
  public void Fall( ) {
    Console.WriteLine("Leaf is falling");
  }
}

public class ExchangeRate {
  public Action Fall {
    get {
      return ( ) =>
        Console.WriteLine("Exchange rate is falling");
    }
  }
}

I also have this helper function:

static void DoFall(dynamic thing) {
  try {
    thing.Fall( );
  }
  catch {
    Console.WriteLine("Turns out {0} can't fall.", thing);
  }
}

I call the helper function like this:

DoFall(new Leaf( ));
DoFall(new ExchangeRate( ));
DoFall(42);

The result is the obvious one:

Leaf is falling
Exchange rate is falling
Turns out 42 can't fall.

But now I call the helper function like this instead:

var things = new dynamic[] {
  new Leaf(),
  new ExchangeRate(),
  42
};

foreach (dynamic thing in things)
  DoFall(thing);

And suddenly the result changes:

Turns out Basics.Leaf can't fall.
Exchange rate is falling
Turns out 42 can't fall.

Suddenly, the method Leaf.Fall can’t be executed anymore… funny that, I would have thought that would be the more obvious of the two implementations in this example. I’ve had a similar difference in behavior before, when I was implementing my own DynamicObject. In that case it came down to different optimizations (?), which the C# compiler apparently applies based on how much it knows about the actual object type at the point of invocation. These resulted in two different call patterns for my own type, where TryInvokeMember would be used in some cases and TryGetMember followed by Invoke in others. I can imagine that something similar is behind this case I’m seeing now, but of course there’s not much I can do about it here, since the types in question are just standard C# classes. Well. I’ll try again with the RC. Meanwhile, if you have any comments, feel free…

Sorry, this blog does not support comments.

I used various blog hosting services since this blog was established in 2005, but unfortunately they turned out to be unreliable in the long term and comment threads were lost in unavoidable transitions. At this time I don't want to enable third-party services for comments since it has become obvious in recent years that these providers invariably monetize information about their visitors and users.

Please use the links in the page footer to get in touch with me. I'm available for conversations on Keybase, Matrix, Mastodon or Twitter, as well as via email.