Dynamically linking to an output type

In The C # Programming Language, Bill Wagner says:

Many people confuse dynamic bindig with output type. The output type is statically linked. 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 says that i is an integer. All bindings to the variable I use static binding.

Now, given this information and my own dynamic dynamics:

        dynamic i = 5;       //Compiler punts
        Console.WriteLine(i);//This is now dynamically bound

      

We know that type inference is statically linked. This means that a dynamic variable cannot use type inference to determine the type. How is a dynamic type resolved without using type inference?

Update
To try and clarify ... at runtime, we have to somehow figure out which type am I right? Since I am assigning a literal 5

, then the runtime can infer what i

is int

. Isn't this a type expression but dynamic binding?

+3


source to share


1 answer


How is Bill different?

The distinction Bill makes is that many people think that:

var x = Whatever();
x.Foo();

      

will work at runtime which method Foo to call based on the type of object returned at runtime by whatever. It is not true; it will be

dynamic x = Whatever();
x.Foo();

      

var

simply means "work out the type at compile time and replace it", not "work with it at runtime".

So, if I have

dynamic i = 5;
Console.WriteLine(i);

      

What's happening?

The compiler generates code that morally looks like this:

object i = (object)5;
DynamicCallSite callSite = new DynamicCallSite(typeof(Console), "WriteLine"));
callSite.Invoke(i);

      

It's a little more complicated than this; the call site is cached, on the one hand. But it gives you a taste of it.

The invocation method queries i

for its type via GetType

, and then runs a special version of the C # compiler that can understand reflection objects. It performs overloading on Console

named members WriteLine

and determines which overload Console.WriteLine

would be called if i

injected as an int in the first place.



It then generates an expression tree representing this call, compiles the expression tree into a delegate, caches it in the invocation site, and invokes the delegate.

The second time you do this, the cached call site looks into its cache and sees that the last time i

an int was a specific delegate was called. So the second time it skips the call site creation and does overload resolution and just calls 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/

For a historical perspective on this feature, check out Chris and Sam's blogs:

http://blogs.msdn.com/b/cburrows/archive/tags/dynamic/

http://blogs.msdn.com/b/samng/archive/tags/dynamic/

They have done a lot to realize; however, some of these articles reflect outdated designs. Unfortunately, we never went with the "Phantom Method" algorithm. (Not a great algorithm, but a great name!)

+6


source







All Articles