Y a-t-il une différence entre les deux instructions suivantes? Ils travaillent tous les deux.Cast à Func vs nouveau Func?
if (((Func<bool>)(()=>true))()) { .... };
if (new Func<bool>(()=>true)()) { .... };
Y a-t-il une différence entre les deux instructions suivantes? Ils travaillent tous les deux.Cast à Func vs nouveau Func?
if (((Func<bool>)(()=>true))()) { .... };
if (new Func<bool>(()=>true)()) { .... };
Non, ils sont tous les deux compilés exactement à la même IL.
Il est plus facile de voir si vous donnez au corps lambda quelque chose qui dépend de l'état - sinon le compilateur met en cache une instance de délégué unique pour chaque lambda. Mais par exemple:
using System;
class Test
{
bool value = DateTime.Now.Hour == 10;
void Cast()
{
if (((Func<bool>)(() => value))())
{
Console.WriteLine("Yes");
}
}
void New()
{
if (new Func<bool>(() => value)())
{
Console.WriteLine("Yes");
}
}
static void Main()
{
new Test().Cast();
new Test().New();
}
}
Maintenant, l'IL pour Cast
est:
.method private hidebysig instance void Cast() cil managed
{
// Code size 39 (0x27)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldftn instance bool Test::'<Cast>b__0'()
IL_0008: newobj instance void class [mscorlib]System.Func`1<bool>::.ctor(object,
native int)
IL_000d: callvirt instance !0 class [mscorlib]System.Func`1<bool>::Invoke()
IL_0012: ldc.i4.0
IL_0013: ceq
IL_0015: stloc.0
IL_0016: ldloc.0
IL_0017: brtrue.s IL_0026
IL_0019: nop
IL_001a: ldstr "Yes"
IL_001f: call void [mscorlib]System.Console::WriteLine(string)
IL_0024: nop
IL_0025: nop
IL_0026: ret
} // end of method Test::Cast
et l'IL pour New
est:
.method private hidebysig instance void New() cil managed
{
// Code size 39 (0x27)
.maxstack 2
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldftn instance bool Test::'<New>b__1'()
IL_0008: newobj instance void class [mscorlib]System.Func`1<bool>::.ctor(object,
native int)
IL_000d: callvirt instance !0 class [mscorlib]System.Func`1<bool>::Invoke()
IL_0012: ldc.i4.0
IL_0013: ceq
IL_0015: stloc.0
IL_0016: ldloc.0
IL_0017: brtrue.s IL_0026
IL_0019: nop
IL_001a: ldstr "Yes"
IL_001f: call void [mscorlib]System.Console::WriteLine(string)
IL_0024: nop
IL_0025: nop
IL_0026: ret
} // end of method Test::New
Comme vous pouvez le voir, ils sont même en dehors de l'appel ldftn
, qui utilise simplement la méthode générée par le compilateur appropriée.
Je suis curieux de savoir pourquoi le compilateur n'utiliserait pas la même instance de délégué ici, puisque les deux fonctions anonymes ont la même variable capturée ('value'). –
Pourquoi 'if ((() => true)())' ne fonctionne pas et doit être casté? Le compilateur devrait être en mesure d'inférer le type de 'Func'? –
ca9163d9
@ dc7a9163d9: Pourquoi? Il peut s'agir d'un type de délégué * any * sans paramètre et d'un type de retour pour lequel 'true' peut être converti. –