动态查找

  如前所述,var关键字本身并不是一个类型,所以并没有违反C#的“强类型化”方法论。但从C# 4开始,一些地方变得没那么死板。C# 4引入了“动态变量”概念,顾名思义,动态变量是类型可变的变量。

  引入动态变量的主要目的是在许多情况下,希望使用C#处理另一种语言创建的对象。这包括与旧技术的交互操作,例如Component Object Model(COM),以及处理动态语言,例如JavaScript、Python和Ruby。这里不详细讨论其实现细节,只需要知道,过去使用C#访问这些语言所创建的对象的方法和属性需要用到笨拙的语法。例如,假定代码从JavaScript中获得了一个带Add()方法的对象,该方法把两个数字加在一起。如果没有动态查找功能,调用这个方法的代码就如下所示:

  1. ScriptObject jsObj = SomeMethodThatGetsTheObject();
  2. int sum = Convert.ToInt32(jsObj.Invoke("Add", 2, 3));

  ScriptObject类型(这里不深入探讨)提供了一种访问JavaScript对象的方式,但仍不能执行如下操作:

  1. int sum = jsObj.Add(2, 3);

  动态查找功能改变了这一切,它允许编写上述代码,但如下面几节所述,这个功能是有代价的。

  另一个可以使用动态查找功能的情形是处理未知类型的C#对象。这听起来似乎很古怪,但这种情形出现的次数比我们想象得多。如果需要编写一些泛型代码来处理接收的各种输入,这也是一项重要功能。处理这种情形的“旧”方法称为“反射(reflection)”,它涉及使用类型信息来访问类型和成员。前一章使用了简单的反射来访问与类型关联的特性。使用发射访问类型成员(如方法)的语法非常类似于上述代码中访问JavaScript对象的语法,也非常麻烦。

  在后台,动态查找功能由Dynamic Language Runtime(动态语言运行库,DLR)支持。与CLR一样,DLR是.NET 4.5的一部分。DLR的精确描述及其如何简化交互操作超出了本书的讨论范围,这里仅对如何在C#中使用它感兴趣。