昨天,我们发表了关于 C# 4.0 中动态查找功能的一些介绍。今天我们来看一些比较奇怪的例子,让大家进一步了解动态查找特性。
将 null 传递给 dynamic
我们来看下面的例子。
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5:6: namespace DynamicDemo
7: {8: class Program
9: {10: static void Main(string[] args)11: {12: dynamic d = null;
13:14: Console.WriteLine(d);15: Console.ReadLine();16: }17: }18: }19:
接下来让我们按 F5 启动该项目,大家猜猜运行结果会怎么样呢?我们得到了如下的异常。
这个异常告诉我们重载决策失败 -- 无法正确决策 Console.WriteLine(char[]) 和 Console.WriteLine(params object[])。
问题到底出在哪里呢?原来,将一个 null 赋值给 dynamic 变量是合法的。其 d 拥有的值为 null,也就是空引用,null 并不是一个 object,它没有类型,因此,Console.WriteLine() 方法认为调用它的实际函数签名是 WriteLine(null),而这个签名匹配 WriteLine(object) 和 WriteLine(char[])。该异常的抛出证明了对 dynamic 进行 null 赋值是可行的。
从 dynamic 到 CLR 类型以及从 CLR 类型到 dynamic
我们再来看一个代码实例。
运行这段代码会在 i = d 语句处抛出异常。因为此时的 d 类型是 System.String,而 System.String 无法隐含转换为 System.Int32。
这个例子说明任何 CLR 类型和 dynamic 类型可以实现隐含的互相转化。
注意:Lambda 表达式不能隐含转换为 dynamic,dynamic 需要一个 delegate 才能正常工作。
dynamic 作为函数参数
下面的代码表示了一些合法和非法的 dynamic 参数的赋值。
大家看到有红线的地方,刚才我们说过的匿名方法和 Lambda 表达式不能转换为 dynamic 外,还有最后一个函数调用,给出来的错误也非常离奇。
我开始严重怀疑这是一个 Bug 了。目前的 Visual Studio 2010 还没有到 Beta 1,所以可以假设这是编译器的 Bug -- 事实上,编译器应该接受这种强制类型转换。报告“未能找到方法 Test 接受 1 个参数的重载决策”明显是不 Make sense 的。
上面的代码我们需要注意的是,多维数组也可以被接受。特别的,如果 value 参数的实际类型为 int[][],此时如果把 Test 的签名改成:
则下面的代码
是可以工作的。那么此时的 value 类型是 dynamic 的数组。