Rightly recognizing that SaySomething doesn't exist in the current context.

This is the scariest thing I've seen all week. And I was in Austin last weekend.

So why does it do this? This goes back to the way that overload resolution is achieved during compilation. Eric Lippert wrote about this problem in C# 3.0 earlier this year. Overload resolution steps (for C# 3.0) are as follows, in this order:

1. First, each overload is examined according to it's arguments. 2. Next the determination of whether or not the overload is accessible from the current static or instance context is made. 3. If the overload selected from step 1 is inaccessible, then a compile-time error is thrown.

Now, let's look at the situation I posed above. The major difference here is when this resolution occurs. The first example actually compiles, because the overload resolution is delayed until runtime. The order of operations, however, stays the same.

At runtime, these steps are performed in the following order:

1. First, each overload is examined according to it's arguments.2. Next the determination of whether or not the overload is accessible from the current static or instance context is made. 3. If the overload selected from step 1 is inaccessible, then a run-time error is thrown.

In other words, the rules are exactly the same as they were in C# 3.0, but the consequences of this mistake while using dynamic are much more severe than they are when not using the dynamic type.

All this to say, the dynamic type is a nice addition to the C# toolbox, but it needs to be used with extreme care.