.Netのリソースのリリースについて少し。
警告:以下
のテキストは、
ロシア語と
英語でネットワーク上にある有名な情報をあなた自身の言葉で単に語ったものです。
.Netでアンマネージリソースを解放する場合はどうすればよいですか? 最後のセクションにリソースリリースコードを配置できます。これが最も簡単な方法です。 あまりエレガントではありませんが、落とし穴なしで動作することが保証されています。
DBConnection conn = new DBConnection();
try
{
conn.Open();
//...
}
finally
{
conn.Close();
}
* This source code was highlighted with Source Code Highlighter .
タスクを複雑にしましょう。 アンマネージリソースで動作するライブラリクラスを作成しました。 意地悪の法則(または多数-必要に応じて)に従って、govnokoderyも教祖を除いてそれを使用します。 アンマネージリソースを解放するメソッドを呼び出すことを静かに忘れています。 そして、彼らは
あなたによって曲がって書かれた図書館に吐き出します。
したがって、ユーザーが自分で呼び出すのを忘れた場合、リソースを解放するメソッド(管理対象または管理対象に関係なく)がガベージコレクターによって自動的に呼び出されるように、クラスを記述します。
管理されていないリソースを解放するには、IDisposableインターフェイスを1つの単一のDispose関数と共に使用して、リソースを解放することをお勧めします。 そして、ここでの主なタスクはこの関数を書くことではなく、この関数が必ず呼び出されるようにコードを書くことです。
次の2つのケースがあります。
1)ユーザーがリソース自体を解放するメソッドを呼び出しました
2)ユーザーがリソースの解放を要求しなかったため、GCがそれに関与する必要がある
最初のオプションは次のようになります。
using (MyClass x = new MyClass())
{
x.SomeMethod();
//...
}
* This source code was highlighted with Source Code Highlighter .
または:
MyClass x;
try
{
x = new MyClass();
x.SomeMethod();
//...
}
finally
{
if (x != null )
x.Dispose();
}
* This source code was highlighted with Source Code Highlighter .
2番目のオプションは次のようになります。
MyClass x = new MyClass();
x.SomeMethod();
//...
* This source code was highlighted with Source Code Highlighter .
MyClassクラス自体とそのDisposeメソッドを実装する方法について考えてみましょう。これらすべての場合にコードが機能しますか? 表面にある要件をリストします。
1)Disposeメソッドは、連続して数回呼び出された場合に失敗するべきではありません(愚か者に対する保護)
2)Disposeメソッドは、明示的に呼び出された場合、GCから呼び出されるべきではありません(したがって、ユーザーが自分で呼び出さなかった場合、GCから呼び出されます)
破棄された変数は、MyClassクラスの提案された実装(既に解放されたクラスと解放されていないクラスを区別できるようにするため)、デストラクタ(GCからDisposeメソッドを呼び出すため)、最後にDispose関数のラッパー-bool Disposeパラメーターを持つ関数に登場したのは、これら2つの考慮事項からですbool manual)(手動破棄と自動破棄を区別するため)。 そうそう。 GC.SuppressFinalize(this)メソッドを使用するには、手動呼び出しを自動呼び出しと区別する必要があります。 デストラクタへの呼び出しを無効にします。
このクラスを取得する合計(msdnからの単純なコピーと貼り付け):
public class MyResource: IDisposable
{
private bool disposed = false ;
// IDisposable
//
//
public void Dispose()
{
Dispose( true ); //
GC.SuppressFinalize( this ); // , GC
}
//
~MyClass()
{
Dispose( false ); // GC
}
//
private void Dispose( bool manual)
{
if (! this .disposed)
{
if (manual)
{
// managed
//...
// - Dispose
// managed -
// Dispose,
// Dispose GC
}
// unmanaged
//...
disposed = true ;
}
}
}
* This source code was highlighted with Source Code Highlighter .
以上です。 MyClassクラスから継承する場合、このコードには多少の複雑さがあります(Dispose(bool)メソッドをオーバーライドして、親クラスのDisposeメソッドへの呼び出しを提供する必要があります)。 しかし、これはそれほど難しくありません。