処分について混乱しています。コードがリソースを正しく破棄できるようにしています。したがって、私はクラスを(Disposeメソッドを使用して)IDisposableとしてセットアップし、Disposeメソッドが呼び出されることを確認しています。
しかし今、FXCopはDisposing = falseとDispose(false)の呼び出しについて多くのことを教えてくれます。
Boolを受け取るDisposeメソッドは見当たりません。作る必要がありますか?もしそうなら、なぜですか?破棄するときに呼び出されるメソッドを用意しないのはなぜですか?
私はここにいくつかのコードを見ました: http://msdn.Microsoft.com/en-us/library/ms244737.aspx これは、ブール値を取るDisposingメソッドの作成方法を示しています。それはそれがネイティブvsマネージドリソースのためであると言います。 しかし、私は処分の全体のポイントは管理されていないリソースのみにあると思っていました。
また、FXCopが不満を言うのは次の行です。
~OwnerDrawnPanel()
{
_font.Dispose();
}
それは言う:
CA1063:Microsoft.Design: 'OwnerDrawnPanel。〜OwnerDrawnPanel()'を変更して、Dispose(false)を呼び出して戻るようにします。
しかし、FontにはDispose(bool)がありません(私が見つけることができます)。
なぜDispose(bool)が必要なのですか?そして、もしそうなら、なぜFontにはないのですか?それがないのに、なぜFXCopはそれを使用するように要求するのですか?
すばらしい回答をありがとう。私は今理解したと思います。ここは
「管理されていない」リソースの破棄は、次の2つのカテゴリに分類されます。
Dispose(bool)は、2つの違いを示すために使用されます。
IDisposable
は、署名付きのメソッドを提供します
_public void Dispose()
_
Microsoftのベストプラクティス( http://msdn.Microsoft.com/en-us/library/fs2xkftw.aspx )は、署名付きの2番目のプライベートメソッドを作成することを推奨しています
_private void Dispose(bool)
_
パブリックDisposeメソッドとFinalizerは、このプライベートDisposeメソッドを呼び出して、管理対象リソースを何度も破棄しないようにする必要があります。
IDisposableを実装してdisposeメソッドでフォントオブジェクトを破棄するか、クラスにDispose(bool)
メソッドを作成して、ファイナライザーがそのメソッドを呼び出すようにすることで、発生している警告を修正できます。
Dispose(bool)
は、Finalize
およびDispose
を実装して管理されていないリソースをクリーンアップするパターンです 詳細はこちらを参照
Dispose(bool)
は公開することを目的としていないため、Font
に表示されません。
クラスの一部のユーザーがメソッドでDisposeを呼び出すのを忘れた場合、Finalizer
でDispose(false)
を呼び出すことにより、アンマネージリソースonlyを解放します。
IDisposeが正しく呼び出された場合は、マネージリソースでDisposeを呼び出し、もアンマネージを処理します。
フラグは2つのケースを区別することです。
これは、MSDNが推奨するパターンです。
FxCopは、 ここに記載されているようにDisposableパターンを実装する必要があると言っています 。 _font
isのような管理対象リソースを破棄する場合は、ファイナライザを使用しないでください。ファイナライザは、管理されていないリソースをクリーンアップするために使用されます。 (サブ)クラスのDisposeメソッドでクリーンアップロジックを実行しない場合、それらはガベージコレクターによって非決定的に実行されます。
また、デストラクタで何かを行う必要があるのは非常にまれであることに注意してください。定期的に、すべてがガベージコレクターによって処理されます。たとえば、コードでは、OwnerDrawnPanel
のデストラクタに_font
オブジェクトを配置する必要はありません。パネルはGCによってクリーンアップされているため、_font
もクリーンアップされます。
一般に、使い捨てオブジェクトを所有している場合は、独自のDispose
メソッドが呼び出されたときにのみ廃棄する必要があります。ただし、デストラクタでは[〜#〜] not [〜#〜]です。デストラクタが実行されているときは、すべての集約オブジェクトもクリーンアップされていることに賭けることができます。
ファイナライザを使用する必要はほとんどありません。これらは直接含むアンマネージリソースのクラス専用であり、.NET 2.0+ではSafeHandleでラップする必要があります。
再度[finalize]を呼び出す必要がないため、Dispose(true)
はマネージリソースとアンマネージリソースの両方を解放すると思います。そのため、GC.SupressFinalize()
の後にDispose(true)
を記述します。
アンマネージリソースを解放するために、デストラクタでDispose(false)
を呼び出します。これは、ユーザーのコードではなく、ランタイムによって呼び出されます。
Kumarに同意すると、Dispose(bool disposing)
パターンも文書化されます MSDNで 。マネージリソースとアンマネージリソースの違いはありませんが、Dispose
がコードによって呼び出されるのか、ランタイムによって呼び出されるのかは異なります。
IDisposeインターフェイスの正しい実装に関する良い記事を見つけました: http://msdn.Microsoft.com/en-us/library/ms244737(v = vs.80).aspx
パブリックpublic void Dispose()
、protected virtual void Dispose(bool)
、および~ClassName()
ファイナライザを実装するパターンは、クリーンアップを適切に整理する方法として、ベストプラクティス Microsoftが推奨 です。マネージリソースとアンマネージリソースの両方のコード。
基本的に、Disposable
クラスを使用するコードはDispose()
を呼び出す必要がありますが呼び出さない場合は、ファイナライザ~ClassName()
を呼び出しますガベージコレクションによって呼び出され、それらのいずれが使用されるかに基づいて、引数をDispose(bool)
にtrueまたはfalseとして設定し、Dispose(bool)
でマネージリソースをクリーンアップするのは、引数は真です。
表示される警告では、ファイナライズメソッド~ClassName()
でこの方法を使用することを特に推奨しているようです。