title: C# closure heap allocation happening at start of method
body: <p>I seem to have run into some odd behavior of the C# compiler.</p>
  
  <p>Consider the following code sample:</p>
  
  <pre><code>static void Main(string[] args)
  {
      Foo(false, 8);
  }
  
  public static void Foo(bool execute, int x)
  {
      if (execute)
      {
          Task.Run(() =&gt; Console.WriteLine(x));
      }
  }
  </code></pre>
  
  <p>Running this (in release) shows some unexpected allocations happening. Examining the IL shows that that the heap allocation triggered by the closure appears at the very start of the function, rather than inside the condition:</p>
  
  <pre><code>  .method public hidebysig static void 
      Foo(
        bool execute, 
        int32 x
      ) cil managed 
    {
      .maxstack 2
      .locals init (
        [0] class Test.Program/'&lt;&gt;c__DisplayClass1_0' 'CS$&lt;&gt;8__locals0'
      )
  
      IL_0000: newobj       instance void Test.Program/'&lt;&gt;c__DisplayClass1_0'::.ctor()
      IL_0005: stloc.0      // 'CS$&lt;&gt;8__locals0'
      IL_0006: ldloc.0      // 'CS$&lt;&gt;8__locals0'
      IL_0007: ldarg.1      // x
      IL_0008: stfld        int32 Test.Program/'&lt;&gt;c__DisplayClass1_0'::x
  
      // [18 13 - 18 25]
      IL_000d: ldarg.0      // execute
      IL_000e: brfalse.s    IL_0022
  
      // [20 17 - 20 54]
      IL_0010: ldloc.0      // 'CS$&lt;&gt;8__locals0'
      IL_0011: ldftn        instance void Test.Program/'&lt;&gt;c__DisplayClass1_0'::'&lt;Foo&gt;b__0'()
      IL_0017: newobj       instance void [mscorlib]System.Action::.ctor(object, native int)
      IL_001c: call         class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Threading.Tasks.Task::Run(class [mscorlib]System.Action)
      IL_0021: pop          
  
      // [22 9 - 22 10]
      IL_0022: ret          
  
    } // end of method Program::Foo
  </code></pre>
  
  <p>Am I missing something here, does anyone has an explanation for this strange behavior? Is it possible that Roslyn generates code which allocates for closures regardless of whether we actually execute them?</p>