IDisposableとdeleteその2

・途中です

IDisposableの実装はDisposeパターンが推奨されていて、C++/CLIでデストラクタ、ファイナライザを書くとこのパターンにのっとってコードが生成されます。

デストラクタ~A()とファイナライザ!A()はそのまま定義され、それらをコールする、Disposeメソッド、Finalizeメソッドが定義されます。以下、実際のC++/CLIがどのようにコンパイルされるかを調べます。

ref class A {
public:
    ~A()
    {
        System::Console::WriteLine("~A()");
    }
};
ref class B : A{
    ~B()
    {
        System::Console::WriteLine("~B()");
    }
};
void testfunc()
{
    A^ a = gcnew A;
    B^ b = gcnew B;
    delete a;
    delete b;
}
int main()
{
    testfunc();
    return 0;
}

このコードをコンパイルし、.NET Reflectorを使ってC#のコードを見ると以下のようになってます。

internal class A : IDisposable
{
    // Methods
    private void ~A()
    {
        Console.WriteLine("~A()");
    }
    public sealed override void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
    {
        if (flag1)
        {
            this.~A();
        }
        else
        {
            base.Finalize();
        }
    }
}
internal class B : A
{
    // Methods
    private void ~B()
    {
        Console.WriteLine("~B()");
    }
    protected override void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
    {
        if (flag1)
        {
            try
            {
                this.~B();
            }
            finally
            {
                base.Dispose(true);
            }
        }
        else
        {
            base.Dispose(false);
        }
    }
}
internal static void modopt(CallConvCdecl) testfunc()
{
    B b = null;
    A a = null;
    a = new A();
    b = new B();
    IDisposable disposable2 = a;
    if (disposable2 != null)
    {
        disposable2.Dispose();
    }
    IDisposable disposable = b;
    if (disposable != null)
    {
        disposable.Dispose();
    }
}
internal static int modopt(CallConvCdecl) main()
{
    testfunc();
    return 0;
}