式木(Expression Tree)と無名delegate

無名delegateの場合は、コンパイル時に無名メソッドそのものがILに生成されるが、式木はメソッドを表現する式そのものがインスタンスとして生成される。

ILで見てみる

こういうコードを書く。

using System;
using System.Linq.Expressions;
namespace Sample
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<string>> a = () => "Hello World A";
            Func<string> b = () => "Hello World B";
            Func<string> c = delegate { return "Hello World C"; };

            Console.WriteLine(a.Compile()());
            Console.WriteLine(b());
            Console.WriteLine(c());
            Console.ReadLine();
        }
    }
}

コンパイルして、ILDasmで覗く。
そうすると、変数bと変数cに対応するメソッドはアセンブリ内に自動定義されているのに対して、変数aに対応するメソッドは出力されていない。

  .method private hidebysig static string 
          '<Main>b__0'() cil managed
  {
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
    // コード サイズ       10 (0xa)
    .maxstack  1
    .locals init ([0] string CS$1$0000)
    IL_0000:  ldstr      "Hello World B"
    IL_0005:  stloc.0
    IL_0006:  br.s       IL_0008

    IL_0008:  ldloc.0
    IL_0009:  ret
  } // end of method Program::'<Main>b__0'

  .method private hidebysig static string 
          '<Main>b__1'() cil managed
  {
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 
    // コード サイズ       11 (0xb)
    .maxstack  1
    .locals init ([0] string CS$1$0000)
    IL_0000:  nop
    IL_0001:  ldstr      "Hello World C"
    IL_0006:  stloc.0
    IL_0007:  br.s       IL_0009

    IL_0009:  ldloc.0
    IL_000a:  ret
  } // end of method Program::'<Main>b__1'