在阅读《CLR via C# (第三版)》第132页看到dynamic这个类型,感觉挺有用的。
记录下来日后查用以及跟园友们分享,内容如下:
为了方便开发人员使用反射或者与基本组件通信,C#编译器允许将一个表达式的类型标记为 dynamic。还可以将一个表达式的结果放到一个变量中,并将变量的类型标记为dynamic。然后,可以用这个 dynamic 表达式/变量调用一个成员,比如字段、属性/索引器、方法、委托以及一元/二元/转换操作符。代码用 dynamic 表达式/变量来调用一个成员时,编译器会生成特殊的 IL 代码来描述所需的操作。这种特殊的代码成为 payload(有效载荷)。在运行时,payload 代码根据当前由 dynamic 表达式/变量引用的对象的实际类型来决定具体执行的操作。
以下代码对此进行了演示:
using System; internal static class DynamicDemo { public static void Main() { for ( int i = 0; i < 2; i++) { dynamic arg = (i == 0) ? (dynamic)5 : (dynamic) "A" ; dynamic result = Plus(arg); M(result); } } private static dynamic Plus(dynamic arg) { return arg + arg; } private static void M( int n) { Console.WriteLine( "M(int):" + n); } private static void M( string s) { Console.WriteLine( "M(string):" + s); } } |
以上代码是经过了测试的,如果在编译过程中出现错误,可能缺少引用,比如:Microsoft.CSharp
------------------------------------------------------------
执行 Main 方法时,会得到以下输出:
M(int):10
M(string):AA
为了理解发生的事情,让我们先来研究以下 Plus 方法。这个方法将参数的类型声明为 dynamic。在方法内部,实参被作为二元+操作符的两个操作数使用。由于 arg 是 dinamic ,所以C#编译器会生成 payload 代码,以便在运行时检查 arg 的实际类型,并决定 + 操作符实际要做的事情。
第一次调用Plus时,传递的是5(一个int),所以Plus向它的调用者返回值10(也是一个int)。结果放到result变量(声明为 dynamic 类型)中。然后调用M方法,将 result 传给它。针对对 M 的调用,编译器会生成 payload 代码,以便在运行时检查传给M的值的实际类型,并决定应该调用 M 方法的哪个重载版本。在 result 包含一个 int 的前提下,调用的是获取一个 int 参数的 M 重载。
第二次调用Plus时,传递的是"A"(一个string),所以 Plus 会将 "AA" ("A"和它自己的连接的结果)传回它的调用者,后者将这个结果放到 result 变量中。然后,再次调用 M 方法,将 result 传给他。 这一次, payload 代码判断出传给 M 的值的实际类型是 String , 所以会调用获取一个 String 参数的 M 重载。
--------------------------------------
以及关于更多的 dynamic 的说明以及实现过程,这里就不做更多的介绍了,园友们可以参考《CLR via C# (第三版)》第133页,或者查下MSDN文档吧