滅入るんるん

何か書きます

【C#】SharpLabを使ってCILを見る

前回・前々回とCILを見るツールを紹介してきたので、SharpLabを紹介しないわけにはいかないだろうということで紹介しておきます。

前回: [C#]ILSpyを使ってCILを見る
前々回: [C#]ReSharperを使ってCILを見る

SharpLabはWebサイト上でC#のコードがコンパイル後どのようになるか確認できるサイトです。

たとえば、この画像のようにC#コードをコンパイル→デコンパイルした結果を見てみることができたり

この画像のようにC#コードをコンパイルしCILになった姿を見てみることができます。

他にも便利機能が多々あって、開発中の最新ブランチのコンパイラーを試したり、C#/CIL以外にもJIT後のアセンブリが見えたり、Debug/Releaseビルドを選択できたりします。

さすがにJIT後のアセンブリは(自分には)読めないですが、Releaseビルドの最適化具合を雰囲気で味わうことができるのは便利ですね。


ただの紹介記事だとつまらないので、最近CILの勉強を頑張ってるのでそれのアウトプット。

さきほどの画像のC#コード

using System;
public class C 
{
    public void M()
    {
    }
}

これのDebugビルド時のCILを見ると

.class private auto ansi '<Module>'
{
} // end of class <Module>

.class public auto ansi beforefieldinit C
    extends [mscorlib]System.Object
{
    // Methods
    .method public hidebysig 
        instance void M () cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 2 (0x2)
        .maxstack 8

        IL_0000: nop
        IL_0001: ret
    } // end of method C::M

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2053
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: nop
        IL_0007: ret
    } // end of method C::.ctor

} // end of class C

と出力されてます。

こちらのコードのコンストラクターの宣言は.method public hidebysig specialname rtspecialname instance void .ctor () cil managedでされていてspecialnameというのは.NET言語的に特別な意味を持つ.methodに付けられるようです。rtspecialnameというのはspecialnameが付けられている.methodのうちランタイムでも特別な意味がある場合に付けるようです。

ちなみに、コンストラクターは.ctorというメソッド名になりますが、静的コンストラクターは.cctorというメソッド名になります。

そして、.ctor内の処理にですが、

IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor() 
IL_0006: nop
IL_0007: ret

とあります。

IL_0001:は見た目の通り基底クラス(System.Object)のコンストラクターを呼んでいます。
そこで、IL_0000:についてですが、.ctorメソッドはinstanceメソッドなのでC#的に言うとthisが必要です。そのthisinstanceメソッドの場合、引数0に格納されています。そこでldarg.0で引数0のthisをスタックに読み込み、その状態でIL_0001:でスタック上のthisを使い基底クラスのコンストラクターを呼ぶのです。
IL_0006:はReleaseビルドでは消されるものであり、何もしない命令のようです。
IL_0007:によって.ctorメソッドがreturnされます。

CILの解釈はだいたいこのようなものだと思いますが、勉強途中なので誤ったことを言っている可能性はあります。間違っていたらコメントでの指摘お願いしますm(__)m

(それとCILのコードハイライト欲しいですね…)