Using the static type of a variable in a dynamic call
As I said before, figuring out when the compiler will dispatch a call dynamically is simple: anytime the receiver or one of the arguments of a call is dynamic. And when using a variable of type dynamic means that the Runtime Binder will use the runtime type of the value stored in that variable and NOT it’s compile-time type. You can read more about compile time versus runtime type in my previous entry.
Let’s first figure out what is a scenario when the RuntimeBinder should use the compile time type of the variable instead of it’s runtime type.
Consider the code below:
1: public class Base
2: {
3: public void Foo(string s) {}
4: }
5: public class Derived : Base
6: {
7: public void Foo(int x) {}
8: }
9:
10: Base obj = new Derived();
11: dynamic d = 4;
12:
13: obj.Foo(d);
At line 11 we instantiate a new Derived class and stick it into a variable of type Base. From the compiler’s perspective, this means when doing overload resolution it should only look at the methods defined by the Base. With that logic, the only method that the compiler should consider for overload resolution is Foo(string).
Because this method call is dispatched dynamically, the RuntimeBinder MUST consider the same set of overloads. If the RuntimeBinder would have used the runtime-type for obj, the methods that would be considered when doing overload resolution would be Foo(string) and Foo(int) since the runtime-type of obj is Derived.
This would lead to some very confusing cases when you are expecting one method to be called and at runtime a different one gets called.
The same reasoning applies to passing arguments that are not typed dynamic to a method call that is dispatched dynamically.
To summarize, there are two cases when the static type of a variable is passed to the RuntimeBinder:
- If the receiver of the call is not typed dynamic but at least one of its arguments is typed dynamic.
- We need to have at least a dynamic argument in the call in order to have the call dispatch dynamically
- If any of the arguments to a dynamically dispatched method call are not typed as dynamic.
An example might explain this better:
int x=4;
dynamic d = new MyClass(); d.Foo(x);
-
Because x is not typed as dynamic, the compiler will pass the information about it’s static type to the RuntimeBinder
The compiler encodes the static type of a variable and passes that information to the RuntimeBinder by using the CallSite object we talked about here.
Feel free to post any questions you might have.