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

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

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的方法:

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)

posted @ 2008-10-30 00:13 new 维生素C.net() 阅读(1971) 评论(11) 编辑 收藏

 回复 引用 查看   
#1楼 2008-10-30 00:19 Astar      
顶一下,明天再看。
 回复 引用   
#2楼 2008-10-30 08:14 Xjog[未注册用户]
怎么感到C#有点失去了简洁的风格了呢
恩。。。。还是C++简法代码少,虽然它怪异

 回复 引用   
#3楼 2008-10-30 09:46 ‖[未注册用户]
到了3.0时代的LINQ,再到4.0时代的Dynamic

效率本来就不高,到linq,dynamic,效率更差,让开发人员不会写sql,我已经往java转了.

 回复 引用 查看   
#4楼 2008-10-30 13:45 沐枫      
dynamic实际上是vb一开始就有的功能。只不过这回引入到c#来了。
 回复 引用 查看   
#5楼 2008-10-30 13:46 沐枫      
这些跟效率无关。只不过是多了几个可选择的工具,用不用在程序员和项目。
@沐枫
是的,VB有,C#现在才有,弥补的就是这之间的差异,优势互补嘛,这次VB也增加了几个新的功能

@‖
技术的进步不见得就是软件效率的显著提高,可能有很多的软件或者程序员关注于高效的应用程序,但也有很多人关注于高效的开发,.NET一样允许你直接使用SQL,只不过是让它适合更多的程序而已。
就现今硬件水平的发展和未来硬件水平的必然发展而言,软件效率的降低未必是件坏事,所谓此消彼长在这里总是有一定的作用的,绝非毫无事处。
用咱的五行阴阳来讲就是物极必反,微软早做准备也是不无道理的。既然是额外的工具,您自然有选择用与不用的权利。

@Xjog
C++也被发展地……

 回复 引用 查看   
#7楼 2008-10-30 16:31 装配脑袋      
开发人员会写SQL又能做什么呢?
 回复 引用 查看   
#8楼 2008-10-31 09:29 devil0153      
全未必是好事,我倒是觉得像vb中的optional的鬼东西完全没必要移植到C#中来,本来重载已经很好了,加入optional绝对是混淆视听,增加复杂性和代码可读性,C#不是动态语言,没必要搞的跟动态语言一样,最后搞的C#成了四不象,完全没了自己的特点,其实linq的加入已经很大程度上受到了质疑,效率,性能不说,在多线程下linq的优势荡然无存,也是"动态"特性搞的鬼,所以什么都有未必是好事.
 回复 引用 查看   
#9楼 2008-10-31 14:59 Steven Chen      
@devil0153
"实linq的加入已经很大程度上受到了质疑,效率,性能不说,在多线程下linq的优势荡然无存,也是"动态"特性搞的鬼,所以什么都有未必是好事."
--------------------貌似恰恰相反哦


谢谢lz的分享,手上的机器也跑不起来4.0,不过从来没有人提到过2010里面的F#是否有踪影,不是说F#已经成为.net的第一语言了么,还想知道,如果让C#和F#交互的话。。。。。。这是不是Dynamic出现的首要原因

 回复 引用   
#10楼 2008-11-01 22:41 J[未注册用户]
C#已经失去纯洁性了,你再动态能动的过人家动态语言吗?
 回复 引用   
#11楼 2009-03-11 11:18 122[未注册用户]
@devil0153
VS2010在多线程下将会有P-LINQ(并行计算的LINQ)哦