ボクシングに関しては、それは違いはありません。次のコードを使用します。
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
これは、最初に使用すると時間がかかる理由を説明するのに役立ちます。何らかのキャッシング メカニズムが実行されていると思われます。つまり、初回以降はパフォーマンスが低下しません。