式木(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'