动态绑定与类型推断

P.B*_*key 3 c# dynamic

C#编程语言中, Bill Wagner说:

许多人将动态绑定与类型推断混淆.类型推断是静态绑定的.编译器在编译时确定类型.例如:

var i = 5;             //i is an int (Compiler performs type inference)
Console.WriteLine(i);  //Static binding to Console.WriteLine(int)
Run Code Online (Sandbox Code Playgroud)

编译器推断i是一个整数.对变量i的所有绑定都使用静态绑定.

现在,根据这些信息和我自己制作的动态场景:

        dynamic i = 5;       //Compiler punts
        Console.WriteLine(i);//This is now dynamically bound
Run Code Online (Sandbox Code Playgroud)

我们知道类型推断是静态约束的.这意味着动态变量无法使用类型推断来确定类型.如何在不使用类型推断的情况下解析动态类型?

更新
要尝试澄清......在运行时我们必须弄清楚我的类型是什么?因为我分配了一个文字,5然后运行时可以推断出它i是一个int.是不是那种类型推断而不是动态绑定?

Eri*_*ert 6

比尔制作的区别是什么?

比尔正在做的区别是许多人认为:

var x = Whatever();
x.Foo();
Run Code Online (Sandbox Code Playgroud)

将在运行时计算出Foo根据Whatever在运行时返回的对象类型调用的方法.这不是真的; 那会是

dynamic x = Whatever();
x.Foo();
Run Code Online (Sandbox Code Playgroud)

var意味着"在编译时计算出类型并将其替换为",而不是"在运行时将其解决".

所以,如果我有

dynamic i = 5;
Console.WriteLine(i);
Run Code Online (Sandbox Code Playgroud)

怎么了?

编译器生成的代码在道德上如下:

object i = (object)5;
DynamicCallSite callSite = new DynamicCallSite(typeof(Console), "WriteLine"));
callSite.Invoke(i);
Run Code Online (Sandbox Code Playgroud)

它有点复杂; 一方面,缓存了呼叫站点.但这给你的味道.

调用方法i通过它来询问其类型GetType,然后启动一个可以理解反射对象的特殊版本的C#编译器.它对Consolenamed 的成员执行重载解析WriteLine,并确定Console.WriteLine将调用的哪个重载首先i被键入为int.

然后,它生成表示该调用的表达式树,将表达式树编译为委托,将其缓存在调用站点中,并调用该委托.

第二次执行此操作时,缓存的调用站点将在其缓存中查看最后一次i是int,并调用了特定的委托.因此,它第二次跳过创建调用站点并执行重载解析,并只调用委托.

有关更多信息,请参阅:

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/

可以从Chris和Sam的博客中获得有关该功能的历史视角:

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

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

他们做了很多实施; 然而,这些文章中的一些反映了过时的设计选择.令人遗憾的是,我们从未使用过"幻影方法"算法.(不是一个很好的算法,但是一个好名字!)