IL_0015: newarr [mscorlib]System.String IL_001a: stloc.s CS$0$0000 IL_001c: ldloc.s CS$0$0000 IL_0025: ldloc.s CS$0$0000 IL_002e: ldloc.s CS$0$0000 } // end of method Program::Main 我们可以看到,在C#
中定义了几种类型,都是以var
定义的,并且都是方法内部的局部变量。但在IL
中我们会看到(红色代码)定义的局部变量会有准确的类型。 下面我们来看一下在vs2010
中,C#4.0
中的一个新的类型dynamic
,我们同样来定义一个方法: var str = new string[] { "a", "b" }; dynamic str1 = new string[] { "a", "b" }; .method private hidebysig static void Main() cil managed .locals init ([0] int32 i, IL_0015: newarr [mscorlib]System.String IL_001a: stloc.s CS$0$0000 IL_001c: ldloc.s CS$0$0000 IL_0025: ldloc.s CS$0$0000 IL_002e: ldloc.s CS$0$0000 IL_0033: box [mscorlib]System.Int32 IL_0043: box [mscorlib]System.Double IL_004f: box [mscorlib]System.Single IL_0057: newarr [mscorlib]System.String IL_005c: stloc.s CS$0$0000 IL_005e: ldloc.s CS$0$0000 IL_0067: ldloc.s CS$0$0000 IL_0070: ldloc.s CS$0$0000 } // end of method File::Main 我们看到C#
中的代码基本没变,就是把var
换成dynamic
,在IL
中,var
的没有变化,但用dynamic
定义的类型(红
色代码部分)
,除了string[]
外都是object
类型,如果这样看来,dynamic
其不是就是object
吗?不是的,往下看,会发现每个类型在初始化时就个box
,就是装箱,装到dynamic
这种类型中了,看来dynamic
是个引用类型,是真的吗? 现在我们从装折箱角度来看一下这dynamic
与object
的区别。 .method private hidebysig static void Method() cil managed
.locals init ([0] int32 i,
IL_0005: box [mscorlib]System.Int32
IL_000c: unbox.any [mscorlib]System.Int32
IL_0013: box [mscorlib]System.Int32
IL_0019: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>> ConsoleApplication2.File/'<Method>o__SiteContainer0'::'<>p__Site1'
IL_001e: brtrue.s IL_0041
IL_0020: call class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder::GetInstance()
IL_0025: ldtoken [mscorlib]System.Int32
IL_002a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0030: newobj instance void [System.Core]Microsoft.CSharp.RuntimeBinder.CSharpConversionPayload::.ctor(class [System.Core]Microsoft.CSharp.RuntimeBinder.RuntimeBinder,
class [mscorlib]System.Type,
valuetype [System.Core]Microsoft.CSharp.RuntimeBinder.CSharpConversionPayload/ConversionKindEnum)
IL_0035: call class [System.Core]System.Scripting.Actions.CallSite`1<!0> class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>>::Create(class [System.Core]System.Scripting.Actions.CallSiteBinder)
IL_003a: stsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>> ConsoleApplication2.File/'<Method>o__SiteContainer0'::'<>p__Site1'
IL_0041: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>> ConsoleApplication2.File/'<Method>o__SiteContainer0'::'<>p__Site1'
IL_0046: ldfld !0 class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>>::Target
IL_004b: ldsfld class [System.Core]System.Scripting.Actions.CallSite`1<class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>> ConsoleApplication2.File/'<Method>o__SiteContainer0'::'<>p__Site1'
IL_0051: callvirt instance !2 class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>::Invoke(!0,
} // end of method File::Method
我们会发现int i
到object o
是box
,object o
到int i
是unbox
,但dynamic d = i; int k = (int)d;
前一行代码是box
,但后一行就不是简单的unbox
,看来object
与dynamic
则是不同的,是一个全新的类型,当然低层做了很多工作。 var
与dynamic
还一个区别是应用范围,var
只能在类成员内部去应用,也就是来充当类成员的局部变量,但dynamic
的应用范围就大了,他和一个基本的类型是一样的,可以在有其他类型的任何地方应用。也就是我们的变量动态到任何地方了,不像var
只是在一定范围内。 dynamic虽然简化了我们的定义,但这是以牺牲系统性能为代价的。所以大家最好能有准确的数据类型。
本文转自桂素伟51CTO博客,原文链接:http://blog.51cto.com/axzxs/149950 ,如需转载请自行联系原作者