Cast to Func vs new Func?

Is there any difference between the following two statement? They both work.

if ( ((Func<bool>)(()=>true))() ) { .... };
if ( new Func<bool>(()=>true)()) { .... };
Jon Skeet
people
quotationmark

No, they both compile to exactly the same IL.

It's easier to see if you actually give the lambda body something that depends on state - otherwise the compiler caches a single delegate instance for each lambda. But for example:

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();
    }
}

Now the IL for Cast is:

.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

and the IL for New is:

.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

As you can see, they're same apart from the ldftn call, which just uses the appropriate compiler-generated method.

people

See more on this question at Stackoverflow