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…