2011-07-23 24 views
5

マルチスレッドアプリケーション用のILを生成したい。最初のステップとして、 私は簡単なアプリケーションを書いて検査し、ILSpyを使ってILを生成しました。匿名メソッド用のILの生成

public class ThreadTesting 
{ 
    public static void Main() 
    { 
     Thread thread = new Thread(() => Print("Hello from t!")); 
     thread.Start(); 
    } 

    public static void Print(string message) 
    { 
     Console.WriteLine(message); 
    } 
} 
.method public hidebysig static 
    void Main() cil managed 
{ 
    // Method begins at RVA 0x2060 
    // Code size 46 (0x2e) 
    .maxstack 3 
    .entrypoint 
    .locals init (
     [0] class [mscorlib]System.Threading.Thread 
    ) 

    IL_0000: nop 
    IL_0001: ldsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 
    IL_0006: brtrue.s IL_001b 

    IL_0008: ldnull 
    IL_0009: ldftn void ThreadTesting::'<Main>b__0'() 
    IL_000f: newobj instance void [mscorlib]System.Threading.ThreadStart::.ctor(object, native int) 
    IL_0014: stsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 
    IL_0019: br.s IL_001b 

    IL_001b: ldsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 
    IL_0020: newobj instance void [mscorlib]System.Threading.Thread::.ctor(class [mscorlib]System.Threading.ThreadStart) 
    IL_0025: stloc.0 
    IL_0026: ldloc.0 
    IL_0027: callvirt instance void [mscorlib]System.Threading.Thread::Start() 
    IL_002c: nop 
    IL_002d: ret 
} // end of method ThreadTesting::Main 

私はSystem.Reflection.Emit 名前空間を使用して上記のILコードの大部分を生成することができました。

残念ながら、私はSystem.Reflection.Emitを使用してILコードの後に​​ を生成する方法を理解できませんでした。

IL_0001: ldsfld class [mscorlib]System.Threading.ThreadStart ThreadTesting::'CS$<>9__CachedAnonymousMethodDelegate1' 

だから誰かが私は匿名メソッドのためのILを生成する方法 を把握するのに役立つことができますか?

答えて

6

ILは単に、コンパイラがデリゲートインスタンスをキャッシュする方法であり、メソッド自体の一部ではありません。 DynamicMethodを使用している場合は、CreateDelegate({あなたのデリゲート型})を呼び出し、必要なデリゲート型(おそらくThreadStart)にキャストし、(型付けされた)デリゲートインスタンスをどこにでも格納します。

4

ILでは「匿名メソッド」という概念はありません。 C#コンパイラが行うことは、言い換えられない名前(<Main>b__0)とメソッドへのデリゲートをキャッシュするための静的フィールド(CS$<>9__CachedAnonymousMethodDelegate1)を持つ通常のメソッドを作成することです。

あなたがするべきことは、あなたがしたいことによって異なります。デリゲートをキャッシュしたくない場合、デリゲートを作成する必要はなく、作成することができます。これにより、コードがいくらか簡略化されます。

匿名メソッドを通常のメソッドに変換し、ILSpyでそれを見ると、簡略化されたIL(ldsfldなし)が表示され、それを生成できます。

+0

キャッシュはおそらくemitを使用してより重要ですが、再利用されることがない場合は、実際に格納する理由はありません。 –

+0

@Marc、私は匿名メソッドとそれを使用するメソッドの両方がemitを使って生成されていると仮定していました。その場合、デリゲートコンストラクタへの呼び出しを1つだけ保存するため、キャッシングはあまり役に立ちません。そうでない場合は、メソッド全体を再度生成することを意味します。もちろん、正しいことです。 – svick

関連する問題