动态查找
动态查找可以用统一的方式来动态调用成员。有了动态查找,当你拿到一个对象时,不用管它是来自于COM还是IronPython、HTML DOM或是反射;只需要对其进行操作即可,运行时会帮你指出针对特定的对象,这些操作的具体意义。
这给你带来了巨大的灵活性,并能极大程度地精简代码,但它伴随着一个巨大的缺点——不会为这些操作维护静态类型。在编译时,会假设动态对象支持任何操作,而如果它不支持某个操作,则只有到运行时才能得到错误。有的时候这不会有任何损失,因为对象根本不具有静态类型,而且他情况下必须在简洁和安全之间进行权衡。为了帮助进行权衡,C#的一个设计目标就是允许在每个单独的调用中选择是否使用动态行为。
类型
C# 4.0引入了一个新的静态类型,称为dynamic。当你拥有了一个dynamic类型的对象后,你“对他做的事情”只会在运行时进行解析——
dynamic d = GetDynamicObject(...);
d.M(7);
C#编译器允许你使用任何参数在d上调用一个方法,因为它的类型是dynamic。运行时会检查d的实际类型,并检测在它上面“用一个int调用M”是什么意思。
可以认为dynamic类型是object类型的一个特殊版本,指出了对象可以动态地使用。选择是否使用动态行为很简单——任何对象都可以隐式转换为dynamic,“挂起信任”直到运行时。反之,从dynamic到任何其他类型都存在“赋值转换”,可以类似于赋值的结构中进行隐式转换——
动态操作
不仅是方法调用,字段和属性访问、索引器和运算符调用甚至委托调用都可以动态地分派——
- d.M(7); // calling methods
- d.f = d.P; // getting and settings fields and properties
- d[“one”] = d[“two”]; // getting and setting thorugh indexers
- int i = d + 3; // calling operators
- string s = d(5,7); // invoking as a delegate
C#编译器在这里的角色就是打包有关“在d上做什么”的必要信息,使得运行时可以获取这些信息并检测对于实际对象d这些操作的确切含义。可以认为这是将编译器的部分工作延迟到了运行时。
任何动态操作的结果本身也是dynamic类型的。