在The C# Programming language比尔瓦格纳说:
许多人将动态绑定与类型推断混为一谈。类型 推理是静态约束的。编译器确定类型 编译时间。例如:
var i = 5; //i is an int (Compiler performs type inference) Console.WriteLine(i); //Static binding to Console.WriteLine(int)
编译器推断i是整数。对变量的所有绑定 我使用静态绑定。
现在,鉴于这些信息和我自己制作的动态场景:
dynamic i = 5; //Compiler punts
Console.WriteLine(i);//This is now dynamically bound
我们知道类型推断是静态绑定的。这意味着动态变量无法使用类型推断来确定类型。如何在不使用类型推断的情况下解析动态类型?
更新
试图澄清......在运行时我们必须弄清楚我的类型是什么?因为我分配了文字5
,所以运行时可以推断出i
是int
。是不是那种类型推断而不是动态绑定?
答案 0 :(得分:6)
比尔制作有什么区别?
比尔正在做的区别是很多人都认为:
var x = Whatever();
x.Foo();
将在运行时根据Whatever在运行时返回的对象类型调用什么方法。这不是真的;那将是
dynamic x = Whatever();
x.Foo();
var
只是意味着“在编译时计算出类型并将其替换为”,而不是“在运行时将其解决”。
所以,如果我有
dynamic i = 5; Console.WriteLine(i);
会发生什么?
编译器生成的代码在道德上如下:
object i = (object)5;
DynamicCallSite callSite = new DynamicCallSite(typeof(Console), "WriteLine"));
callSite.Invoke(i);
比这复杂一点;一方面,缓存了呼叫站点。但是这给你的味道。
调用方法通过i
向GetType
询问其类型,然后启动可以理解反射对象的特殊版本的C#编译器。它对名为Console
的{{1}}成员执行重载解析,并确定在WriteLine
首先将Console.WriteLine
作为int键入时调用了哪个重载。< / p>
然后生成表示该调用的表达式树,将表达式树编译为委托,将其缓存在调用站点中,并调用该委托。
第二次执行此操作时,缓存的调用站点会在其缓存中查看最后一次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/
他们做了很多实施;然而,这些文章中的一些反映了过时的设计选择。令人遗憾的是,我们从未使用过“幻影方法”算法。 (不是一个很好的算法,但是一个好名字!)