1

オブジェクト型よりも動的型を使用する場合

Boxing/UnBoxing のオーバーヘッドを克服できる天候はありますか?

void Print(dynamic p)
{
     Console.WriteLine(string.Format("{0} : {1}", p.GetType(),p));
}

void Print(object p)
{
     Console.WriteLine(string.Format("{0} : {1}", p.GetType(),p));
}

両方の方法から、どちらが効率的でプロセッサに優しいでしょうか?

4

3 に答える 3

2

ボクシングに関しては、それは違いはありません。次のコードを使用します。

public class TestClass
{
    static void Test()
    {
        int v = 5;    // Create an unboxed value type variable
        PrintDynamic(v);
    }

    static void PrintDynamic(dynamic p)
    {

    }
}

メソッドTest()を IL に逆コンパイルすると、次のようになります。

.method private hidebysig static void  Test() cil managed
{
  // Code size       16 (0x10)
  .maxstack  1
  .locals init ([0] int32 v)
  IL_0000:  nop
  IL_0001:  ldc.i4.5
  IL_0002:  stloc.0
  IL_0003:  ldloc.0
  IL_0004:  box        [mscorlib]System.Int32
  IL_0009:  call       void ConsoleApplication6.Session::PrintDynamic(object)
  IL_000e:  nop
  IL_000f:  ret
} 

Testの引数がとして宣言されているにもかかわらずdynamic、整数がボックス化されていることがわかります。

編集

タイミングの不一致についての質問に答えて、次の方法を検討してください。

    static void Print(object p)
    {
        string.Format("{0}", p);
    }

    static void PrintDynamic(dynamic p)
    {
        string.Format("{0}", p);
    }

最初の IL は次のようになります。

.method private hidebysig static void  Print(object p) cil managed
{
  // Code size       14 (0xe)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "{0}"
  IL_0006:  ldarg.0
  IL_0007:  call       string [mscorlib]System.String::Format(string,
                                                              object)
  IL_000c:  pop
  IL_000d:  ret
} // end of method TestClass::Print

2番目の場合:

.method private hidebysig static void  PrintDynamic(object p) cil managed
{
  .param [1]
  .custom instance void [System.Core]System.Runtime.CompilerServices.DynamicAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       123 (0x7b)
  .maxstack  8
  .locals init ([0] class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo[] CS$0$0000)
  IL_0000:  nop
  IL_0001:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`4<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,string,object>> ConsoleApplication6.TestClass/'<PrintDynamic>o__SiteContainer0'::'<>p__Site1'
  IL_0006:  brtrue.s   IL_0055
  IL_0008:  ldc.i4     0x100
  IL_000d:  ldstr      "Format"
  IL_0012:  ldnull
  IL_0013:  ldtoken    ConsoleApplication6.TestClass
  IL_0018:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_001d:  ldc.i4.3
  IL_001e:  newarr     [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo
  IL_0023:  stloc.0
  IL_0024:  ldloc.0
  IL_0025:  ldc.i4.0
  IL_0026:  ldc.i4.s   33
  IL_0028:  ldnull
  IL_0029:  call       class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,
                                                                                                                                                                             string)
  IL_002e:  stelem.ref
  IL_002f:  ldloc.0
  IL_0030:  ldc.i4.1
  IL_0031:  ldc.i4.3
  IL_0032:  ldnull
  IL_0033:  call       class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,
                                                                                                                                                                             string)
  IL_0038:  stelem.ref
  IL_0039:  ldloc.0
  IL_003a:  ldc.i4.2
  IL_003b:  ldc.i4.0
  IL_003c:  ldnull
  IL_003d:  call       class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo::Create(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags,
                                                                                                                                                                             string)
  IL_0042:  stelem.ref
  IL_0043:  ldloc.0
  IL_0044:  call       class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::InvokeMember(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,
                                                                                                                                                               string,
                                                                                                                                                               class [mscorlib]System.Collections.Generic.IEnumerable`1<class [mscorlib]System.Type>,
                                                                                                                                                               class [mscorlib]System.Type,
                                                                                                                                                               class [mscorlib]System.Collections.Generic.IEnumerable`1<class [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)
  IL_0049:  call       class [System.Core]System.Runtime.CompilerServices.CallSite`1<!0> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`4<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,string,object>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
  IL_004e:  stsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`4<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,string,object>> ConsoleApplication6.TestClass/'<PrintDynamic>o__SiteContainer0'::'<>p__Site1'
  IL_0053:  br.s       IL_0055
  IL_0055:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`4<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,string,object>> ConsoleApplication6.TestClass/'<PrintDynamic>o__SiteContainer0'::'<>p__Site1'
  IL_005a:  ldfld      !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`4<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,string,object>>::Target
  IL_005f:  ldsfld     class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Action`4<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,string,object>> ConsoleApplication6.TestClass/'<PrintDynamic>o__SiteContainer0'::'<>p__Site1'
  IL_0064:  ldtoken    [mscorlib]System.String
  IL_0069:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_006e:  ldstr      "{0}"
  IL_0073:  ldarg.0
  IL_0074:  callvirt   instance void class [mscorlib]System.Action`4<class [System.Core]System.Runtime.CompilerServices.CallSite,class [mscorlib]System.Type,string,object>::Invoke(!0,
                                                                                                                                                                                    !1,
                                                                                                                                                                                    !2,
                                                                                                                                                                                    !3)
  IL_0079:  nop
  IL_007a:  ret
} // end of method TestClass::PrintDynamic

dynamicこれは、最初に使用すると時間がかかる理由を説明するのに役立ちます。何らかのキャッシング メカニズムが実行されていると思われます。つまり、初回以降はパフォーマンスが低下しません。

于 2013-10-18T11:14:39.323 に答える
0

まったく違いはありません。マイクロソフトから:

ダイナミック型は、ほとんどの状況でオブジェクト型のように動作します。ただし、dynamic 型の式を含む操作は、コンパイラによって解決または型チェックされません。

http://msdn.microsoft.com/en-us/library/vstudio/dd264741.aspx

このことから、ダイナミックは式で使用されるまでオブジェクトとして機能すると推測します。これには、パラメーターの受け渡しが含まれます。

于 2013-10-18T10:52:42.067 に答える