Führt der folgende Code zum Boxen der ganzen Zahl, die an den Aufruf von GenericMethod
übergeben wurde?Wird ein generischer Typ mit dem dynamischen Schlüsselwort cause boxing umgewandelt?
Antwort
Gemäß C# -Spezifikation §4.7 Der dynamische Typ:
dynamic
ist identisch betrachtetobject
außer in folgenden Punkten:
Operationen auf Ausdrücke vom Typ
dynamic
dynamisch gebunden werden (§7.2.2).Typ Rückschluss (§7.5.2) wird
dynamic
überobject
bevorzugen, wenn beide Kandidaten sind.
So Gießen, zu dynamic
Ursache Boxen auf die gleiche Weise wie auf object
Gießen.
Variablen vom Typ dynamisch werden in Variablen vom Typ Objekt kompiliert, Typ dynamisch existiert nur zur Kompilierzeit, nicht zur Laufzeit.
Also macht Ihr Beispiel tatsächlich Cast auf ein Objekt, das ein Referenztyp ist. Boxen existiert hier
Mal sehen, IL-Code zu sehen, ob Boxen gibt es:
IL_0000: nop
IL_0001: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> class Test.Program/'<>o__0`1'<!!T>::'<>p__0'
IL_0006: brfalse.s IL_000a
IL_0008: br.s IL_002e
IL_000a: ldc.i4.0
IL_000b: ldtoken [mscorlib]System.Int32
IL_0010: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_0015: ldtoken Test.Program
IL_001a: call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
IL_001f: call class [System.Core]System.Runtime.CompilerServices.CallSiteBinder [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.Binder::Convert(valuetype [Microsoft.CSharp]Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, class [mscorlib]System.Type, class [mscorlib]System.Type)
IL_0024: call class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>>::Create(class [System.Core]System.Runtime.CompilerServices.CallSiteBinder)
IL_0029: stsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> class Test.Program/'<>o__0`1'<!!T>::'<>p__0'
IL_002e: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> class Test.Program/'<>o__0`1'<!!T>::'<>p__0'
IL_0033: ldfld !0 class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>>::Target
IL_0038: ldsfld class [System.Core]System.Runtime.CompilerServices.CallSite`1<class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>> class Test.Program/'<>o__0`1'<!!T>::'<>p__0'
IL_003d: ldarg.0
IL_003e: box !!T
IL_0043: callvirt instance int32 class [mscorlib]System.Func`3<class [System.Core]System.Runtime.CompilerServices.CallSite, object, int32>::Invoke(!0, !1)
IL_0048: stloc.0
IL_0049: ret
Wie Sie aus dieser Codezeile sehen können:
IL_003e: box !!T
Es Boxen die int
Ich mag deine Antwort, weil sie mir etwas über IL-Code beigebracht hat, obwohl PetSeri dich um ein paar Minuten gebracht hat. Ich bin hin- und hergerissen, welcher Aspekt wichtiger ist. – Slight
Danke und keine Sorgen, ich bin froh, dass meine Antwort etwas hilfreich war. Zu guter Letzt können Sie IL-Code mit jedem Dekompilierungswerkzeug untersuchen, wie ReSharper dotCover oder Teleriks 'JustDecompile' (JD) – Fabjan
Ich habe ILSpy in der Vergangenheit schon einige Male benutzt, aber nie realisiert, dass es einen expliziten "Box" Opcode gibt. – Slight
Der dynamische Versand wird um Größenordnungen teurer als Boxen, also ist es hier nicht einmal wirklich relevant. – Servy