匿名メソッドは実際には匿名ではありません。コンパイラが生成した名前の後ろに隠れているだけです。
この小さな例を考えてみましょう。
Func<int, int> a = (x) => x + 1;
Console.WriteLine(a.Invoke(1));
戻り値を見つけるには、メソッド実装の名前を見つける必要があります。そのためには、周囲のメソッドのMethodDescを見つける必要があります。この例ではMain()
、次のようになります。
0:000> !name2ee * TestBench.Program.Main
Module: 6db11000 (mscorlib.dll)
--------------------------------------
Module: 00162c5c (TestBench.exe)
Token: 0x06000001
MethodDesc: 00163010
Name: TestBench.Program.Main()
JITTED Code Address: 001e0070
MethodDescを介して、次のILをダンプできます。Main()
0:000> !dumpil 00163010
ilAddr = 003f2068
IL_0000: nop
IL_0001: ldstr "press enter"
IL_0006: call System.Console::WriteLine
IL_000b: nop
IL_000c: call System.Console::ReadLine
IL_0011: pop
IL_0012: ldsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1
IL_0017: brtrue.s IL_002c
IL_0019: ldnull
IL_001a: ldftn TestBench.Program::<Main>b__0
IL_0020: newobj class [System.Core]System.Func`2<int32,int32>::.ctor
IL_0025: stsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1
IL_002a: br.s IL_002c
IL_002c: ldsfld TestBench.Program::CS$<>9__CachedAnonymousMethodDelegate1
IL_0031: stloc.0
IL_0032: ldloc.0
IL_0033: ldc.i4.1
IL_0034: callvirt class [System.Core]System.Func`2<int32,int32>::Invoke
IL_0039: call System.Console::WriteLine
IL_003e: nop
IL_003f: ret
変な格好の名前に注目してください。これらは、生成デリゲートタイプと実際のメソッドの名前です。このメソッドはと呼ばれ<Main>b__0
ます。メソッドを見てみましょう:
0:000> !name2ee * TestBench.Program.<Main>b__0
Module: 6db11000 (mscorlib.dll)
--------------------------------------
Module: 00152c5c (TestBench.exe)
Token: 0x06000003
MethodDesc: 00153024
Name: TestBench.Program.<Main>b__0(Int32)
Not JITTED yet. Use !bpmd -md 00153024 to break on run.
そこにあります。MethodDescは00153024であり、コメントにあるように、!bpmdを使用して、MethodDescを使用してブレークポイントを設定できます。