c#4.0新特性之一: Dynamic Lookup (2)

时间:2022-05-25 05:35:06

我们分析一下用Reflector看到的东西:

c#4.0新特性之一: Dynamic Lookup (2)c#4.0新特性之一: Dynamic Lookup (2)Code

 

首先,编译器生成了__SiteContainer0的本地变量来保存我们的CallSite的内容,然后我们注意到test已经是object类型。由此看来这不能算是什么真正的“动态类型”,只不过算是个“帮助方法”罢了。

接下来代码会检查这个CallSite是否是null,如果是,就是用CallSite.Create并且传递一个CSharpCallPayload的对象作为参数,这个对象保存了所有我们将要去调用的方法的信息。如果这个CallSite不为null,就把这个方法的所有的所有内“附着”到foo这个对象上了。

编译器就是做了这两步,实现了这种动态的功能。

以上内容来自Justin Etheredge的blog,该blog的后文还比较了dynamic的效率问题,经过他的测试,使用var和使用dynamic造成的天壤之别使其性能也有天壤之别,6ms:2106ms。但是我刚看到这测试的时候就觉得不太恰当,如果您自己运行一下dynamic的程序就知道一启动的时候总以为程序出问题了一点反应都没有,过了一会才出结果,也就是runtime上第一次handle这些东东是要有较高时间消耗的,但是这个情况只有一开始加载的时候才会出现,所以比较效率的这组数字不能说的太准确,更何况两者不是干同一个活的,一个是八路,一个是地下工作者,没法比。不过Justin兄弟刚又更新了一篇blog,又重新分析了这个测试,并增加了测试的case,还是挺不错的,值得一看。

Dynamic lookup特性使我们可以使用一种统一的方式动态的invoke其他资源,通过它,我们的对象不需要关心是来在COM,IronPython还是reflection,我们只需要将需要的东西apply给它(熟悉javascript的朋友看到apply就明白dynamic的思想了吧),在runtime时.net自动帮我们搞定剩下的工作。

这给我们的开发给予了巨大的灵活性,但是dynamic object在编译时是闭着眼睛过去的,所以对于运行时能否正确通过,我们就比较麻烦了。

从上面的reflect后的代码我们能看到dynamic类型可以被认为是一个特殊版本的object——只是标记了这个对象能被动态的使用,任何对象都可以被显时的转换为dynamic类型。相反的,还有一种assignment conversion(赋值转换)可以将dynamic类型转换为其他类型:

dynamic d = 7; // implicit conversion
int i = d; // assignment conversion

当然,不只方法可以这么用,字段、属性、索引器、操作符和委托都可以dynamic:

dynamic d = GetDynamicObject(…);
d.M(7); // calling methods
d.f = d.P; // getting and settings fields and properties
d["one"] = d["two"]; // getting and setting through indexers
int i = d + 3; // calling operators
string s = d(5,7); // invoking as a delegate

对于运行时的lookup,dynamic机制是根据它的目标对象来确定的,就是说new的是啥玩意,就通过这个东东来确定怎么lookup,对待COM是通过IDispatch,对于Dynamic对象是通过IDynamicObject,对于标准的.net对象就是用反射,这些内容从微软的官方文档里就能很容易看明白。

拿微软的一个例子来说一下dynamic的一个应用:

我们写一个IronPython的方法:

c#4.0新特性之一: Dynamic Lookup (2)c#4.0新特性之一: Dynamic Lookup (2)Code


存为helloworld.py

然后用ScriptRuntime py = Python.CreateRuntime();建立IronPython的运行环境,用dynamic helloworld = py.UseFile("helloworld.py");来建立动态类型helloworld,就可以使用helloworld.welcome("cnblogs guy");来打印出结果来了。

很爽吧?做silverlight的也不用死盯着一门语言不放了。

C#与Java的攀比从2.0的泛型开始逐渐占据上风,到了3.0时代的LINQ,再到4.0时代的Dynamic,不得不说优势的显著。但是技术终归是个工具,工具生来就是被利用的,我同意冯大辉的观点,使用现有技术足够做好现在市场需要的需求了。不管开发速度有多快,产品架构有多好,我们还是应该多离开code去看看我们的用户究竟在想什么。不要除了coding就是用“我在做俯卧撑”来回答用户的问题。

c#4.0新特性之一: Dynamic Lookup (1)