vs2010新特性(下)

1)    dynamic

C#3.0中有一个动态类型,var,它可以定义不同的类型,系统在第一次编译时会根据上下文来判断这个变量的准确类型。

下面看个例子:

C#代码:

static void Main(string[] args)

        {

            var i = 10;

            var d = 1.2;

            var f = 1.1f;

            var str = new string[] { "a","b"};

        }

IL代码:

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

{

 .entrypoint

 // 代码大小       50 (0x32)

 .maxstack 3

 .locals init ([0] int32 i,

           [1] float64 d,

           [2] float32 f,

           [3] string[] str,

           [4] string[] CS$0$0000)

 IL_0000: nop

 IL_0001: ldc.i4.s   10

 IL_0003: stloc.0

 IL_0004: ldc.r8     1.2

 IL_000d: stloc.1

 IL_000e: ldc.r4     1.1

  IL_0013: stloc.2

 IL_0014: ldc.i4.2

 IL_0015: newarr     [mscorlib]System.String

 IL_001a: stloc.s    CS$0$0000

 IL_001c: ldloc.s    CS$0$0000

 IL_001e: ldc.i4.0

 IL_001f: ldstr      "a"

 IL_0024: stelem.ref

 IL_0025: ldloc.s    CS$0$0000

 IL_0027: ldc.i4.1

 IL_0028: ldstr      "b"

 IL_002d: stelem.ref

 IL_002e: ldloc.s    CS$0$0000

 IL_0030: stloc.3

 IL_0031: ret

} // end of method Program::Main

我们可以看到,在C#中定义了几种类型,都是以var定义的,并且都是方法内部的局部变量。但在IL中我们会看到(红色代码)定义的局部变量会有准确的类型。

下面我们来看一下在vs2010中,C#4.0中的一个新的类型dynamic,我们同样来定义一个方法:

static void Main()

        {

            var i = 10;

            var d = 1.2;

            var f = 1.1f;

            var str = new string[] { "a", "b" }; 

     

            dynamic i1 = 10;

            dynamic d1 = 1.2;

            dynamic f1 = 1.1f;

            dynamic str1 = new string[] { "a", "b" }; 

        }

再来看看他的IL

.method private hidebysig static void Main() cil managed

{

 .entrypoint

 // Code size       117 (0x75)

 .maxstack 3

 .locals init ([0] int32 i,

           [1] float64 d,

           [2] float32 f,

           [3] string[] str,

           [4] object i1,

           [5] object d1,

           [6] object f1,

           [7] object str1,

           [8] string[] CS$0$0000)

 IL_0000: nop

 IL_0001: ldc.i4.s   10

 IL_0003: stloc.0

 IL_0004: ldc.r8     1.2

 IL_000d: stloc.1

 IL_000e: ldc.r4     1.1

 IL_0013: stloc.2

 IL_0014: ldc.i4.2

 IL_0015: newarr     [mscorlib]System.String

 IL_001a: stloc.s    CS$0$0000

 IL_001c: ldloc.s    CS$0$0000

 IL_001e: ldc.i4.0

 IL_001f: ldstr      "a"

 IL_0024: stelem.ref

 IL_0025: ldloc.s    CS$0$0000

 IL_0027: ldc.i4.1

 IL_0028: ldstr      "b"

 IL_002d: stelem.ref

 IL_002e: ldloc.s    CS$0$0000

 IL_0030: stloc.3

 IL_0031: ldc.i4.s   10

 IL_0033: box        [mscorlib]System.Int32

 IL_0038: stloc.s    i1

 IL_003a: ldc.r8     1.2

 IL_0043: box        [mscorlib]System.Double

 IL_0048: stloc.s    d1

 IL_004a: ldc.r4     1.1

 IL_004f: box        [mscorlib]System.Single

 IL_0054: stloc.s    f1

 IL_0056: ldc.i4.2

 IL_0057: newarr     [mscorlib]System.String

 IL_005c: stloc.s    CS$0$0000

 IL_005e: ldloc.s    CS$0$0000

 IL_0060: ldc.i4.0

 IL_0061: ldstr      "a"

  IL_0066: stelem.ref

 IL_0067: ldloc.s    CS$0$0000

 IL_0069: ldc.i4.1

 IL_006a: ldstr      "b"

 IL_006f: stelem.ref

 IL_0070: ldloc.s    CS$0$0000

 IL_0072: stloc.s    str1

 IL_0074: ret

} // end of method File::Main

我们看到C#中的代码基本没变,就是把var换成dynamic,在IL中,var的没有变化,但用dynamic定义的类型(红色代码部分),除了string[]外都是object类型,如果这样看来,dynamic其不是就是object吗?不是的,往下看,会发现每个类型在初始化时就个box,就是装箱,装到dynamic这种类型中了,看来dynamic是个引用类型,是真的吗?

现在我们从装折箱角度来看一下这dynamicobject的区别。

     static void Method()

        {         

            int i = 10;

            object o = i;

            int j = (int)o;

         

            dynamic d = i;

            int k = (int)d;

        }

来看一下IL

.method private hidebysig static void Method() cil managed

{

 // Code size       89 (0x59)

  .maxstack 4

 .locals init ([0] int32 i,

           [1] object o,

           [2] int32 j,

           [3] object d,

           [4] int32 k)

 IL_0000: nop

 IL_0001: ldc.i4.s   10

 IL_0003: stloc.0

 IL_0004: ldloc.0

 IL_0005: box        [mscorlib]System.Int32

 IL_000a: stloc.1

 IL_000b: ldloc.1

 IL_000c: unbox.any [mscorlib]System.Int32

 IL_0011: stloc.2

 IL_0012: ldloc.0

 IL_0013: box        [mscorlib]System.Int32

 IL_0018: stloc.3

 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_002f: ldc.i4.1

 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_003f: br.s       IL_0041

 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_0050: ldloc.3

 IL_0051: callvirt   instance !2 class [System.Core]System.Func`3<class [System.Core]System.Scripting.Actions.CallSite,object,int32>::Invoke(!0,

                                                                                                                                               !1)

 IL_0056: stloc.s    k

 IL_0058: ret

} // end of method File::Method

我们会发现int iobject oboxobject oint iunbox,但dynamic d = i; int k = (int)d;前一行代码是box,但后一行就不是简单的unbox,看来objectdynamic则是不同的,是一个全新的类型,当然低层做了很多工作。

vardynamic还一个区别是应用范围,var只能在类成员内部去应用,也就是来充当类成员的局部变量,但dynamic的应用范围就大了,他和一个基本的类型是一样的,可以在有其他类型的任何地方应用。也就是我们的变量动态到任何地方了,不像var只是在一定范围内。

dynamic虽然简化了我们的定义,但这是以牺牲系统性能为代价的。所以大家最好能有准确的数据类型。
****欢迎关注我的asp.net core系统课程****
《asp.net core精要讲解》 https://ke.qq.com/course/265696
《asp.net core 3.0》 https://ke.qq.com/course/437517
《asp.net core项目实战》 https://ke.qq.com/course/291868
《基于.net core微服务》 https://ke.qq.com/course/299524
原文地址:https://www.cnblogs.com/axzxs2001/p/1341368.html