In The C# Programming language Bill Wagner says:
Many people confuse dynamic binding with type inference. Type
inference is statically bound. The compiler determines the type at
compile time. For example:var i = 5; //i is an int (Compiler performs type inference) Console.WriteLine(i); //Static binding to Console.WriteLine(int)The compiler infers that i is an integer. All binding on the variable
i uses static binding.
Now, given this information and my own made-up dynamic scenerio:
dynamic i = 5; //Compiler punts
Console.WriteLine(i);//This is now dynamically bound
We know type inference is statically bound. This implies that there is no way a dynamic variable can use type inference to determine a type. How does a dynamic type get resolved without using type inference?
Update
To try and clarify…at runtime we must somehow figure out what type i is right? Because I assign a literal 5 then the runtime can infer that i is an int. Isn’t that type inference rather than dynamic binding?
The distinction that Bill is making is that many people think that:
will work out at runtime what method Foo to call based on the type of object returned at runtime by Whatever. That’s not true; that would be
The
varjust means "work out the type at compile time and substitute it in", not "work it out at runtime".The compiler generates code that is morally like this:
It is a bit more complicated than that; the call site is cached, for one thing. But this gives you the flavour of it.
The invocation method asks
ifor its type viaGetTypeand then starts up a special version of the C# compiler that can understand reflection objects. It does overload resolution on the members ofConsolenamedWriteLine, and determines which overload ofConsole.WriteLinewould have been called hadibeen typed as int in the first place.It then generates an expression tree representing that call, compiles the expression tree into a delegate, caches it in the call site, and invokes the delegate.
The second time you do this, the cached call site looks in its cache and sees that the last time that
iwas int, a particular delegate was invoked. So the second time it skips creating the call site and doing overload resolution, and just invokes the delegate.For more information, see:
http://ericlippert.com/2012/10/22/a-method-group-of-one/
http://ericlippert.com/2012/11/05/dynamic-contagion-part-one/
http://ericlippert.com/2012/11/09/dynamic-contagion-part-two/
A historical perspective on the feature can be obtained from Chris and Sam’s blogs:
http://blogs.msdn.com/b/cburrows/archive/tags/dynamic/
http://blogs.msdn.com/b/samng/archive/tags/dynamic/
They did a lot of the implementation; however some of these article reflect outdated design choices. We never did go with "The Phantom Method" algorithm, regrettably. (Not a great algorithm, but a great name!)