【发布时间】:2014-07-12 04:30:28
【问题描述】:
以下两种说法有区别吗?他们都工作。
if ( ((Func<bool>)(()=>true))() ) { .... };
if ( new Func<bool>(()=>true)()) { .... };
【问题讨论】:
以下两种说法有区别吗?他们都工作。
if ( ((Func<bool>)(()=>true))() ) { .... };
if ( new Func<bool>(()=>true)()) { .... };
【问题讨论】:
不,它们都编译为完全相同的 IL。
更容易看出你是否真的给了 lambda 主体一些依赖于状态的东西 - 否则编译器会为每个 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();
}
}
现在Cast 的 IL 是:
.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
New 的 IL 是:
.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 调用之外,它们是相同的,只是使用了适当的编译器生成的方法。
【讨论】:
if ( (()=>true)() ) 不起作用,需要强制转换?编译器应该能够推断出Func<bool>的类型?
true 可以转换为的返回类型。