4
以下两种说法有什么区别吗?他们都工作。强制转换为Func vs new Func?
if (((Func<bool>)(()=>true))()) { .... };
if (new Func<bool>(()=>true)()) { .... };
以下两种说法有什么区别吗?他们都工作。强制转换为Func vs new Func?
if (((Func<bool>)(()=>true))()) { .... };
if (new Func<bool>(()=>true)()) { .... };
不,它们都编译到完全相同的IL。
更容易看到实际上是否给予lambda body一些依赖于状态的东西 - 否则编译器会为每个lambda缓存一个委托实例。但是,例如:
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();
}
}
现在IL为Cast
是:
.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
和IL为New
是:
.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
正如你可以看到,他们是相同的除了调用ldftn
,它只是使用适当的编译器生成的方法。
我很好奇为什么编译器不会在这里使用相同的委托实例,因为这两个匿名函数具有相同的捕获变量('值')。 –
为什么'((()=> true)())'不起作用,它需要被铸造?编译器应该能够推断'Func'的类型? –
ca9163d9
@ dc7a9163d9:为什么?它可以是* any *委托类型,没有任何参数,并且可以转换为'true'的返回类型。 –