Framework 4.0 新关键字dynamic 之我见(一)

大家好,好久没有写博客了,最近一段时间工作也比较忙,不过我还是会在空余时间去学习一些东西。

微软在这个星期一,开放了VS2010和Framework4.0的Beta1版本的下载,所以我也花了1天的时间进行了下载和安装,因为系统现在是windows7,而且这次版本也是beta版本,所以把它安装在了虚拟机上,虽然只设置了1G的内存,不过跑起来还非常让人满意,没有像其他兄弟说的,很吃内存,很废cpu。

其实先前已经使用过CTP版本了,也一直对新特性在做研究,在第一时间下载了beta版本后,发现其实和CTP版本区别不是很大。好了,废话不说了,说说今天的主题吧。

在Framework 4.0 中,微软加入了新的关键字:dynamic 根据字的中文含义,我们就知道了,动态,一切都为动态。有了这个关键字,我们在写代码时就可以不用确定某个变量、属性、方法(不包含void方法,文中所说的方法都是不包含void的)的类型了,一切都交给Framework吧。或许有人会说更var好像一样,其实两者一点都不一样,这会在后面跟大家说说。先来看一段简单的代码:

static void Main(string[] args)

{

dynamic dynamicValue;

dynamicValue = DateTime.Now;

Console.WriteLine(dynamicValue.ToString("yyyy-MM-dd"));

Console.WriteLine(dynamicValue.GetType());

Console.Read();

}

非常简单的一段代码,我们用dynamic定义了一个变量,然后给它赋了一个时间类型的值,随后打印DateTime.ToString()方法,再打印这个动态变量的类型出来。这里要说一点,也是非常重要的一点:

Dynamic 在没有运行的时候,是一个Object类型,其实也可以说没有Type的,它是在Runtime时才被确定是那种类型,所以这里的.ToString()方法,在IDE中是没有任何智能感知的,有点回到记事本的时代了,呵呵。

其实在CTP版本中,已经是这样了,不过我觉得,虽然他在编译时不能确定他的类型,但所有的类型都是继承于Object类型的,为什么智能感知没有把Object的几个共有方法给感知出来呢???(我等了一个版本还是这样,真有点失望)。

那我们来看看,到底程序为什么那么慢吧。用IL DASM看看。


.method private hidebysig static void Main(string[] args) cil managed

{

.entrypoint

// Code size 396 (0x18c)

.maxstack 12

.locals init ([0] object dynamicValue,

[1] class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo[] CS$0$0000)

IL_0000: nop

IL_0001: call valuetype [mscorlib]System.DateTime [mscorlib]System.DateTime::get_Now()

IL_0006: box [mscorlib]System.DateTime

IL_000b: stloc.0

IL_000c: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,object>> ConsoleApplication1.Program/'<Main>o__SiteContainer0'::'<>p__Site1'

IL_0011: brtrue.s IL_0052

IL_0013: ldc.i4.0

IL_0014: ldstr "WriteLine"

IL_0019: ldtoken ConsoleApplication1.Program

IL_001e: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)

IL_0023: ldnull

IL_0024: ldc.i4.2

IL_0025: newarr [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo

IL_002a: stloc.1

IL_002b: ldloc.1

IL_002c: ldc.i4.0

IL_002d: ldc.i4.s 33

IL_002f: ldnull

IL_0030: newobj instance void [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::.ctor(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,

string)

IL_0035: stelem.ref

IL_0036: ldloc.1

IL_0037: ldc.i4.1

IL_0038: ldc.i4.0

IL_0039: ldnull

IL_003a: newobj instance void [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::.ctor(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,

string)

IL_003f: stelem.ref

IL_0040: ldloc.1

IL_0041: newobj instance void [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder::.ctor(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpCallFlags,

string,

class [mscorlib]System.Type,

class [mscorlib]System.Collections.Generic.IEnumerable`1<class [mscorlib]System.Type>,

class

//省略N行

IL_0093: stelem.ref

IL_0094: ldloc.1

IL_0095: ldc.i4.1

IL_0096: ldc.i4.3

IL_0097: ldnull

IL_0098: newobj instance void [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::.ctor(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,

string)

IL_009d: stelem.ref

IL_009e: ldloc.1

IL_009f: newobj instance void [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpInvokeMemberBinder::.ctor(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpCallFlags,

string,

class [mscorlib]System.Type,

class [mscorlib]System.Collections.Generic.IEnumerable`1<class [mscorlib]System.Type>,

class [mscorlib]System.Collections.Generic.IEnumerable`1<class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)

IL_00a4: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,string,object>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)

IL_00a9: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,string,object>> ConsoleApplication1.Program/'<Main>o__SiteContainer0'::'<>p__Site2'

IL_00ae: br.s IL_00b0

IL_00b0: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,string,object>> ConsoleApplication1.Program/'<Main>o__SiteContainer0'::'<>p__Site2'

IL_00b5: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,string,object>>::Target

IL_00ba: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,string,object>> ConsoleApplication1.Program/'<Main>o__SiteContainer0'::'<>p__Site2'

IL_00bf: ldloc.0

IL_00c0: ldstr "yyyy-MM-dd"

IL_00c5: callvirt instance !3 class [mscorlib]System.Func`4<class [System.Core]System.Runtime.CompilerServices.CallSite,object,string,object>::Invoke(!0,

!1,

!2)

IL_00ca: callvirt instance void class [mscorlib]System.Action`3<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,object>::Invoke(!0,

!1,

!2)

//再次省略N行

IL_0184: nop

IL_0185: call int32 [mscorlib]System.Console::Read()

IL_018a: pop

IL_018b: ret

} // end of method Program::Main

 

 

晕死了,那么一大推东西,我们先看看初始化吧,原来编译器在这里把dynamic的变量类型定义成了object,因为是不确定的类型,所以。。。。它把System.Type进行迭代了(大概是这么个意思吧)。我的理解是,它先定义成object类型,然后在Runtime时,在用Invoke去调用ToString方法,省略的部分还有很多,其实都是因为它的不确定性,动态特性,所以把所有可能的类型都列举了出来,然后通过在runtime 的时候再判断和中类型,Invoke相应的方法。

 

现在知道了吧,为什么会这么慢,初始是object Type 免不了要装箱、拆箱,还要Invoke等,能不慢吗?不过测试下来,如果你用了一个Int类型的话,程序会明显的快很多,其中的原因,大家也可以研究一下。

Dynamic虽然是个好东西,不过因为很多时候的不确定因素,让程序在第一次运行的时候会造成很大程度的性能损耗,所以我建议大家一定要慎用,而且在你使用了dynamic类型后,因为它的动态特性,你将失去智能提示这个优越的功能。当然,

Dynamic也有它的好处,因为只需要在运行时第一次确定好类型后,它会变成强类型,这样在后面的运行中,会大大提高效率,而且使用起来也比较方便,免去了烦人的拆箱、装箱工作。

 

今天最后说说和var跟dynamic的区别,我们都知道var能在编译时确定类型,而且也有智能感知,但是var只能在局部使用(方法体),而且必须初始时赋予它值,它才能在编译时去确定是何种类型,不过他们都有一个特点,就是为了程序在后面的运行时,所有的类型都是强类型,至于强类型的好处,大家可以找找博客园中其他大大的一些好文章。

 

很晚了,今天就到这里了,后面的文章会谈谈dynamic在其他方面的性能比较,不过总体下来不是很理想,有点鸡肋的感觉了,感觉微软在这块做的真的不是很好,呵呵。

时间: 2024-09-24 01:21:45

Framework 4.0 新关键字dynamic 之我见(一)的相关文章

Framework 4.0 新关键字dynamic 之我见(二)

Hi,大家好,随着大家对VS2010的深入了解,对dynamic已经是越来越了解了,何时该用,何时不用已经非常熟悉了,原本不打算再写下去的,但感觉还有点东西需要说说,就简单再说一下吧. 原先以为dynamic实在runtime时确定的,后来看了一下,这个runtime是在微软新出的一个运行时DLR上的,动态的为你判断该使用何种类型,而不是原先的CLR,具体的大家可以参考微软的MSDN,因为英文不太好,以免误导大家,也就不写详细了. 这几天一直在考虑何时去用这个关键字,如果对于一般的程序在没有与其

C# 4.0新特性dynamic有何用?

这两天看到园子里面有几篇关于dynamic怎么用的文章,咋一看搞不明白这个 dynamic到底有啥用,反而让我多了两个问题: 写程序时少了智能感知: 运行程序时速度变慢(反射). 今天看完New features in CSharp 4.docx才恍然明白,趁着没事,把东西整 理一下,希望能对暂时还不明白dynamic有什么用的朋友提供一些参考.当然,由 于本人才疏学浅,不保证所有的观点都是正确的,希望大家用辩证的眼光来看这 篇文章,如有错误之处,请大伙批评指正. 言归正传,dynamic关键字

c# 4.0新特性一览

终于静下心来仔细听了一遍Anders Hejlsberg(Visual Studio组的TECHNICAL FELLOW,C#的设计者之 一)在PDC08上讲的"The Future of C#"(http://channel9.msdn.com/pdc2008/TL16/). 回顾C#发展的历史,C#1.0完全是模仿Java,并保留了C/C++的一些特性如struct,新学者很容易上手 :C#2.0加入了泛型,也与Java1.5的泛型如出一辙:C#3.0加入了一堆语法糖,并在没有修改

.Net Framework 4.0 功能介绍

.Net Framework 4.0 功能介绍 微软发布了 Visual Studio 2010 和 .NET Framework 4.0 的Beta 2测试版,微软往Framework 4.0里又塞了很多新东西,有的确实不错,不过有的还是感觉有点粗糙,还在实验阶段,实用性不强. 简单回顾下历史,.Net Framework 1.1其实是个试验品,.Net Framework真正走向成熟其实从2.0开始的,之后的Framework 3,Framework 3.5其实都是基于Framework 2

C# 3.0 新特性:扩展方法初探

C#3.0中一个激动人心的特性就是扩展方法:你可以使用实例方法的语法来调用静态方法.本文仔细阐述了这一新特性并且给出了几个相应的例子. 声明扩展方法 扩展方法的行为和静态方法是非常类似的,你只能在静态类中声明它们.为声明一个扩展方法,你需要给该方法的第一个参数指定this关键字,如下例: // Program.cspublic static class EMClass{ public static int ToInt32Ext(this string s) { return Int32.Pars

.NET Framework 4.0 Beta1里的Expression Tree一例

既然装上了Visual Studio 2010 Beta 1,正好可以试试.NET Framework 4.0里的一些新东西.我比较关注的是Expression Tree的部分,到底哪些功能进到了.NET 4,哪些还得到CodePlex的DLR站上去找呢?试用一下找找感觉. 我暂时没试这个beta里的C#对dynamic的支持,是因为暂时还没想到啥有趣的场景能写点简单的代码来玩的.对.NET类型故意使用dynamic的玩法在之前CTP的时候就玩过了,不过瘾了.回头针对.NET 4来编译一个Iro

c# 6.0新特性(一)

写在前面 接近年底了,基本上没什么活了,就学点新东西,就想着了解下c# 6.0的新特性.在code project上看到了一篇不错的文章,就准备翻译一下,顺便照着学习学习.废话不多说,直奔主题. 原文地址:http://www.codeproject.com/Articles/1070659/All-About-Csharp-New-Features 简介 众所周知,c# 6.0 是在visual studio 2015中引入的.在其他的几个版本中同样引入一些特性,比如在c# 3.0中引入了li

C# 3.0 新特性----扩展方法

转自 http://www.cnblogs.com/jiejie_peng/archive/2010/04/08/1707195.html C# 3.0 新特性----扩展方法 主要目的掌握对一个已经编译的类的方法的扩展 特别注意a. 扩展某个类时,新建的类要使用 public static 修饰,因为默认的类是 internal 访问修饰符b. 这个类要有文件作用域,即不能作为嵌套类使用c. 扩展方法要声明为静态的d. 扩展方法的第一个参数类型即是要扩展的类,且该参数前要加 this 关键字e

F4何去何从 --- 大视野观察Framework 4.0

Framework 4.0 CTP版发布一个多月了,在此期间稍有闲暇就打开来试试,尝试一下这个新东东.总体感觉微软现在技术大爆炸,一下子往F4里塞了好多东西,有的确实不错, 不过有的还是感觉有点粗糙,还经不起实战考验.那以下我会简单和大家过一遍这个新的框架,一起来聊聊F4的前景. 简单回顾下历史,F1.1其实是个试验品,.Net Framework真正走向成熟其实从F2开始的,之后的F3,F3.5其实都是基于F2的扩充,我个人感觉应该定义为F2.1,F2.2.没想到微软喜欢搞大跃进,随便加点东西