Warum fügt der Compiler einen zusätzlichen Parameter für Delegierte hinzu, wenn keine Schließung vorliegt?
Ich habe mit @ gespiedelegates
und bemerkte, dass, wenn ich ein @ erstellFunc<int,int,int>
wie im folgenden Beispiel:
Func<int, int, int> func1 = (x, y) => x * y;
Die Signatur der vom Compiler generierten Methode entspricht nicht meinen Erwartungen:
Wie Sie sehen können, benötigt es ein Objekt für den ersten Parameter. Aber wenn es eine Schließung gibt:
int z = 10;
Func<int, int, int> func1 = (x, y) => x * y * z;
Alles funktioniert wie erwartet:
Dies ist der IL-Code für die Methode mit dem zusätzlichen Parameter:
.method private hidebysig static int32 '<Main>b__0'(object A_0,
int32 x,
int32 y) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )
// Code size 8 (0x8)
.maxstack 2
.locals init ([0] int32 V_0)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: mul
IL_0003: stloc.0
IL_0004: br.s IL_0006
IL_0006: ldloc.0
IL_0007: ret
} // end of method Program::'<Main>b__0'
Es scheint, dass der ParameterA_0
wird nicht einmal verwendet. Also, was ist der Zweck desobject
Parameter im ersten Fall? Warum wird es nicht hinzugefügt, wenn ein Abschluss vorliegt?
Hinweis Wenn Sie eine bessere Idee für den Titel haben, können Sie diese gerne bearbeiten.
Anmerkung 2 Ich habe den ersten Code in beiden kompiliertDebug
undRelease
Modi gab es keinen Unterschied. Aber ich kompilierte den zweiten Platz inDebug
-Modus, um ein Schließverhalten zu erhalten, da die lokale Variable in @ optimiert wiRelease
mode.
Notiz 3 Ich benutzeVisual Studio 2014 CTP
.
Bearbeiten Dies ist der generierte Code fürMain
im ersten Fall
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 30 (0x1e)
.maxstack 2
.locals init ([0] class [mscorlib]System.Func`3<int32,int32,int32> func1)
IL_0000: nop
IL_0001: ldsfld class [mscorlib]System.Func`3<int32,int32,int32> ConsoleApplication9.Program::'CS.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 30 (0x1e)
.maxstack 2
.locals init ([0] class [mscorlib]System.Func`3<int32,int32,int32> func1)
IL_0000: nop
IL_0001: ldsfld class [mscorlib]System.Func`3<int32,int32,int32> ConsoleApplication9.Program::'CS$<>9__CachedAnonymousMethodDelegate1'
IL_0006: dup
IL_0007: brtrue.s IL_001c
IL_0009: pop
IL_000a: ldnull
IL_000b: ldftn int32 ConsoleApplication9.Program::'<Main>b__0'(object,
int32,
int32)
IL_0011: newobj instance void class [mscorlib]System.Func`3<int32,int32,int32>::.ctor(object,
native int)
IL_0016: dup
IL_0017: stsfld class [mscorlib]System.Func`3<int32,int32,int32> ConsoleApplication9.Program::'CS$<>9__CachedAnonymousMethodDelegate1'
IL_001c: stloc.0
IL_001d: ret
} // end of method Program::Main
lt;>9__CachedAnonymousMethodDelegate1'
IL_0006: dup
IL_0007: brtrue.s IL_001c
IL_0009: pop
IL_000a: ldnull
IL_000b: ldftn int32 ConsoleApplication9.Program::'<Main>b__0'(object,
int32,
int32)
IL_0011: newobj instance void class [mscorlib]System.Func`3<int32,int32,int32>::.ctor(object,
native int)
IL_0016: dup
IL_0017: stsfld class [mscorlib]System.Func`3<int32,int32,int32> ConsoleApplication9.Program::'CS.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 30 (0x1e)
.maxstack 2
.locals init ([0] class [mscorlib]System.Func`3<int32,int32,int32> func1)
IL_0000: nop
IL_0001: ldsfld class [mscorlib]System.Func`3<int32,int32,int32> ConsoleApplication9.Program::'CS$<>9__CachedAnonymousMethodDelegate1'
IL_0006: dup
IL_0007: brtrue.s IL_001c
IL_0009: pop
IL_000a: ldnull
IL_000b: ldftn int32 ConsoleApplication9.Program::'<Main>b__0'(object,
int32,
int32)
IL_0011: newobj instance void class [mscorlib]System.Func`3<int32,int32,int32>::.ctor(object,
native int)
IL_0016: dup
IL_0017: stsfld class [mscorlib]System.Func`3<int32,int32,int32> ConsoleApplication9.Program::'CS$<>9__CachedAnonymousMethodDelegate1'
IL_001c: stloc.0
IL_001d: ret
} // end of method Program::Main
lt;>9__CachedAnonymousMethodDelegate1'
IL_001c: stloc.0
IL_001d: ret
} // end of method Program::Main