为了方便开发人员使用反射或者与基本组件通信,c#编译器允许将一个表达式的类型标记为dynamic。还可将一个表达式的结果放到一个变量中,并将变量的类型标记为dynamic,然后,用这个dynamic表达式调用一个成员。如下面代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 static void Main(string[] args) 2 { 3 for (int i = 0; i < 2; i++) 4 { 5 dynamic arg = (i == 0) ? (dynamic)5 : (dynamic)"A"; 6 dynamic result = Plus(arg); 7 M(result); 8 } 9 Console.ReadKey(); 10 } 11 public static dynamic Plus(dynamic arg) { return arg + arg; } 12 public static void M(int n) { Console.WriteLine("M(int32):"+n); } 13 public static void M(string s) { Console.WriteLine("M(string):" + s); }
执行后得到以下输出:
下面来具体分析一下其运行过程。
首先,Plug方法的参数类型为dynamic。在方法内部,实参被作为二元+操作符的两个操作数使用。由于arg是dynamic,c#编译器会生成payload(.Net动态语言)代码,以便在运行时检查arg的实际类型,并决定+所要完成的事情。
当第一次调用Plug时,传递的是int类型,所以Plug向其调用者返回10,并将结果放到result变量中。然后调用M,将result传给它。针对M的调用,编译器会生成payload代码,以便在运行时检查传给M的实际类型,并决定调用M的哪个重载。
第二次调用Plug时,传递的是string类型,所以Plug会返回AA并放到result中。然后调用M。此时,payload代码判断出传给M的值得实际类型是string,因此调用获取string类型的重载。
任何表达式都能隐式的转型为dynamic。正常情况下,编译器不允许将object隐式转为其他类型,然而允许使用隐式语法将表达式从dynamic转为其他类型:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Object o = 123; //OK 从int隐式转为object(装箱) int n1 = o; //ERROR 不允许从object到int的隐式转换 int n2 = (int)o; //OK 从object到int的显式转换(拆箱) dynamic d1 = 123 ; //OK 从int隐式转为dynamic(装箱) int n3 = d1; //OK 从dynamic到int的隐式转换(拆箱)