4.3.5 dynamic类型

dynamic类型是C#4.0引入的全新类型,它允许其操作略过编译期类型检查,而在运行时处理。dynamic类型简化了对COM API的调用(例如对Office组件的COM Interop调用),增强了对动态语言的支持(例如IronPython库),简化了对于HTML文档对象模型(DOM)的访问。

dynamic类型在绝大多数情况下和object类型相似,不同点在于,编译器对于包含了dynamic类型的表达式不做进一步解析和类型检查。编译器将这些信息收集到一起,用于在运行时鉴定操作。实际上,dynamic类型的变量被编译成object类型的变量,因此,dynamic类型只存在于编译期,而运行时并不存在,如图4-13所示。

4.3.5 dynamic类型 - 图1

图 4-13 dynamic类型

我们一起来看如下的示例,如代码清单4-12所示。

代码清单4-12 dynamic类型用法


1 using System;

2

3 namespace ProgrammingCSharp4

4{

5 class Program

6{

7 static void Main(string[]args)

8{

9 dynamic dyn=1;

10 object obj=1;

11

12 Console.WriteLine(dyn.GetType());

13 Console.WriteLine(obj.GetType());

14

15//dyn+=1;//编译通过

16//obj+=1;//编译失败

17}

18}

19}


输出结果为:


System.Int32

System.Int32


dyn是dynamic类型变量,在编译期并不知道它的类型,因此,虽然知道1是System.Int32类型,但因dynamic类型变量在编译期并不解析也不做类型检查,因此1的类型信息被编译期收集起来,在运行时根据该信息确定dyn是System.Int32类型的变量,此时dyn就已经不再是dynamic类型的变量了,而是System.Int32类型,因此才会有上述结果。图4-14说明了动态类型在编译期和运行时的类型。

4.3.5 dynamic类型 - 图2

图 4-14 动态类型

我们再做个实验,首先将第15行的注释去除,然后按Shift+F6进行编译,此时应该顺利编译通过;然后将第16行的注释去除[1],再编译,这时会产生一个编译错误:

运算符“+=”无法应用于"object"和"int"类型的操作数

信息显示:“+=”操作符无法应用于object类型和int类型,obj必须强制转换为int型的变量。为什么dyn变量可以呢?因为编译期不对dynamic变量进行类型检查,因此在编译期dyn很容易就过编译器这一关了,到了运行时就更不用说了,那是dynamic的天下,运行时判定dyn变量为System.Int32类型,因此执行"+="运算是完全合法的,关于运算符的详细内容,请参阅第6章。

使用dynamic类型要注意以下几个问题:

❑由于dynamic类型的变量在设计时类型是未知的,因此你无法看到Visual Studio对dynamic类型变量的成员进行自动提示,因为无法提示;

❑由于dynamic类型变量的具体类型要在运行时才能确定,因此你对该变量的成员调用必须是正确的,如果调用了变量没有的属性或方法,将会产生异常。

[1]删掉行首的“//”符号。