Throw in Func vs New Func?

Is there a difference between the following two statements? They both work.

if ( ((Func<bool>)(()=>true))() ) { .... };
if ( new Func<bool>(()=>true)()) { .... };
+4
source share
1 answer

No, they both compile the same way.

It’s easier to see if you really give the lambda body something that depends on the state - otherwise the compiler caches one 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 IL for 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

and IL for 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

As you can see, they are the same except for a call ldftnthat simply uses the appropriate method created by the compiler.

+10
source

Source: https://habr.com/ru/post/1548130/


All Articles