クラスコンストラクターの最後の例外など、すべての場合にクラスのメンバー変数が確実にクリーンアップされるようにする方法を探していました。
これらはメンバー変数であるため、「try、catch」および「using」パターンは役に立ちません。.NET C ++(C ++ / clr:safe)は、auto_ptrやshared_ptrなどのスマートポインター(msclr :: auto_handleと呼ばれる)のエミュレーションを提供することに気づきました。これは、スレッドやソケットなどの限られたリソースを非常にクリーンな方法で決定論的に破棄できるため、非常に便利です。
私はC++/ clrで生成されたILを分析していて、実際に行われているように見えるのは、カプセル化されたデータを変更するすべての関数でtry/faultsを使用してILをスパムすることだけであることに気付きました。
興味のある人のためにILリストを含めました。(try / faultは私によって追加されたのではなく、C ++ / clrコンパイラによって追加されました)
MyClass()
{
myDisposable.reset(gcnew MyDisposable());
throw gcnew Exception("Hello World");
// myDisposable needs to clean up now
// because it is very large or locks a limited resource.
// Luckily with RAII.. it does!
}
...になります...
.try
{
IL_0006: ldarg.0
IL_0007: ldloc.0
IL_0008: stfld class msclr.'auto_handle<MyDisposable>' modreq([mscorlib]System.Runtime.CompilerServices.IsByValue) MyClass::myDisposable
IL_000d: ldarg.0
IL_000e: call instance void [mscorlib]System.Object::.ctor()
IL_0013: ldarg.0
IL_0014: ldfld class msclr.'auto_handle<MyDisposable>' modreq([mscorlib]System.Runtime.CompilerServices.IsByValue) MyClass::myDisposable
IL_0019: newobj instance void MyDisposable::.ctor()
IL_001e: call instance void msclr.'auto_handle<MyDisposable>'::reset(class MyDisposable)
IL_0023: ldstr "Hello World"
IL_0028: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_002d: throw
IL_002e: leave.s IL_003c
} // end .try
fault
{
IL_0030: ldarg.0
IL_0031: ldfld class msclr.'auto_handle<MyDisposable>' modreq([mscorlib]System.Runtime.CompilerServices.IsByValue) MyClass::myDisposable
IL_0036: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_003b: endfinally
} // end handler
私のソフトウェアは非常に複雑になり、これらすべてを自分で処理することは非常に危険でバグが発生しやすいため、C#でこれを達成する同様の方法はありますか?では、この追加のILコードを自動的に追加して、C#でRAIIをエミュレートできるようにする手法や、ビルド後の手順を知っている人はいますか?
編集:(別の例)
ref class MyClass
{
private:
msclr::auto_handle<MyDisposable> myDisposable;
public:
MyClass()
{
myDisposable.reset(gcnew MyDisposable());
throw gcnew Exception("Hello World");
// myDisposable needs to clean up now because it is very large or locks a limited resource.
}
};
myDisposableはメンバー変数です。コンストラクターから「HelloWorld」がスローされると、myDisposableは実際にはすぐに破棄されます。C#で同じ機能を利用できますか?使用はメンバー変数上にあり、すべての関数でのtry / catchは非常に貧弱な解決策であるため、使用できないことを確認しました。
よろしくお願いします、
Karsten