【问题标题】:Dynamic binding vs type inference动态绑定与类型推断
【发布时间】:2013-02-13 17:54:20
【问题描述】:

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

我们知道类型推断是静态绑定的。这意味着动态变量无法使用类型推断来确定类型。不使用类型推断如何解析动态类型?

更新
为了尝试澄清......在运行时我们必须以某种方式找出 i 是正确的类型?因为我分配了文字5,所以运行时可以推断iint。那不是类型推断而不是动态绑定吗?

【问题讨论】:

  • 动态的底层类型(它是一种语言结构,除了属性之外在元数据中没有表示形式)是System.Object。它是 C# 编译器的魔力,允许您动态调用方法并访问其上的字段(在本例中为装箱的 int),而无需自己进行反射。

标签: c# dynamic


【解决方案1】:

比尔有什么区别?

比尔所做的区别在于,许多人认为:

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

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

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);

比这要复杂一些;一方面,调用站点被缓存。但这给了你它的味道。

调用方法通过GetTypei 询问其类型,然后启动可以理解反射对象的特殊版本的C# 编译器。它对名为 WriteLineConsole 的成员进行重载决策,并确定如果首先将 i 键入为 int,将调用 Console.WriteLine 的哪个重载。

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

第二次执行此操作时,缓存的调用站点在其缓存中查找,并看到上次 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/

他们做了很多实施;然而,其中一些文章反映了过时的设计选择。遗憾的是,我们从未使用过“幻影法”算法。 (不是一个伟大的算法,但一个伟大的名字!)

【讨论】:

  • 我明白了,所以dynamic 没有经历第 7.5.2 节中定义的类型推断过程。相反,i.GetType() 用于在运行时确定类型。
  • 或者更确切地说......在您更新后,他正在比较 vardynamic。这是有道理的!
  • @P.Brian.Mackey:第 7.5.2 节是通用方法类型推断。 Bill 正在谈论的部分是第 8.5.1 节关于隐式类型局部变量声明
猜你喜欢
  • 1970-01-01
  • 2018-08-15
  • 2014-08-27
  • 1970-01-01
  • 2023-02-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 2018-03-12
相关资源
最近更新 更多