ご指摘のとおり、C++/CLI では ~ClassName と !ClassName を実装し、C++/CLI コンパイラは Dispose(void) と Dispose(bool) を書き込みます。
HashAlgorithm から派生させてみたところ、破棄とファイナライズの両方を機能させることができました。おそらく、いくつかのメソッドを宣言する方法に微妙な違いがあります。
ここに私のテストコードがあります:
public ref class CppDispose : HashAlgorithm
{
private:
~CppDispose() { Debug::WriteLine("~CppDispose"); }
!CppDispose() { Debug::WriteLine("!CppDispose"); }
protected:
virtual void HashCore(array<Byte>^ aray, int ibStart, int cbSize) override { }
virtual array<Byte>^ HashFinal() override { return nullptr; }
public:
virtual void Initialize() override { }
};
int main(array<System::String ^> ^args)
{
{
CppDispose foo;
Debug::WriteLine("Disposing: ");
}
{
CppDispose^ foo = gcnew CppDispose();
Debug::WriteLine("Finalizing: ");
foo = nullptr;
GC::Collect();
}
return 0;
}
出力:
廃棄:
~CppDispose
ファイナライズ:
!CppDispose
舞台裏で何が起こっているかを確認できるように、C++/CLI コンパイラが作成したメソッドを C# 構文に逆コンパイルしたものを次に示します。この場合、親クラスには Dispose(void) が実装されているため、ここでは再実装されていません。
[HandleProcessCorruptedStateExceptions]
protected override void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
{
if (flag1)
{
try
{
this.~CppDispose();
}
finally
{
base.Dispose(true);
}
}
else
{
try
{
this.!CppDispose();
}
finally
{
base.Dispose(false);
}
}
}
protected override void Finalize()
{
this.Dispose(false);
}