web-dev-qa-db-ja.com

Dispose vs Dispose(bool)

処分について混乱しています。コードがリソースを正しく破棄できるようにしています。したがって、私はクラスを(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つのカテゴリに分類されます。

  1. マネージクラス(ビットマップ、フォントなど)にラップされているが、適切にクリーンアップするためにDisposeを呼び出す必要があるリソース。
  2. ネイティブリソースの表現である、割り当てたリソース(つまり、解放する必要のあるデバイスコンテキスト)

Dispose(bool)は、2つの違いを示すために使用されます。

  1. オブジェクトでDisposeが直接呼び出された場合、両方の種類の「アンマネージ」リソースを解放する必要があります。
  2. オブジェクトがガベージコレクションの対象になっている場合は、最初の種類のリソースについて心配する必要はありません。ガベージコレクターは、それらをクリーンアップするときにそれらを処理します。必要なのは、割り当てた真のネイティブリソース(存在する場合)だけです。
37
Vaccano

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)メソッドを作成して、ファイナライザーがそのメソッドを呼び出すようにすることで、発生している警告を修正できます。

7
Kyle Trauberman

Dispose(bool)は、FinalizeおよびDisposeを実装して管理されていないリソースをクリーンアップするパターンです 詳細はこちらを参照

9
Kumar

Dispose(bool)は公開することを目的としていないため、Fontに表示されません。

クラスの一部のユーザーがメソッドでDisposeを呼び出すのを忘れた場合、FinalizerDispose(false)を呼び出すことにより、アンマネージリソースonlyを解放します。

IDisposeが正しく呼び出された場合は、マネージリソースでDisposeを呼び出し、アンマネージを処理します。

フラグは2つのケースを区別することです。

これは、MSDNが推奨するパターンです。

7
Aryabhatta

FxCopは、 ここに記載されているようにDisposableパターンを実装する必要があると言っています_font isのような管理対象リソースを破棄する場合は、ファイナライザを使用しないでください。ファイナライザは、管理されていないリソースをクリーンアップするために使用されます。 (サブ)クラスのDisposeメソッドでクリーンアップロジックを実行しない場合、それらはガベージコレクターによって非決定的に実行されます。

3
m0sa

また、デストラクタで何かを行う必要があるのは非常にまれであることに注意してください。定期的に、すべてがガベージコレクターによって処理されます。たとえば、コードでは、OwnerDrawnPanelのデストラクタに_fontオブジェクトを配置する必要はありません。パネルはGCによってクリーンアップされているため、_fontもクリーンアップされます。

一般に、使い捨てオブジェクトを所有している場合は、独自のDisposeメソッドが呼び出されたときにのみ廃棄する必要があります。ただし、デストラクタでは[〜#〜] not [〜#〜]です。デストラクタが実行されているときは、すべての集約オブジェクトもクリーンアップされていることに賭けることができます。

2
Fyodor Soikin

ファイナライザを使用する必要はほとんどありません。これらは直接含むアンマネージリソースのクラス専用であり、.NET 2.0+ではSafeHandleでラップする必要があります。

2
Mark Sowul

再度[finalize]を呼び出す必要がないため、Dispose(true)はマネージリソースとアンマネージリソースの両方を解放すると思います。そのため、GC.SupressFinalize()の後にDispose(true)を記述します。

アンマネージリソースを解放するために、デストラクタでDispose(false)を呼び出します。これは、ユーザーのコードではなく、ランタイムによって呼び出されます。

2
Ratnesh Sinha

Kumarに同意すると、Dispose(bool disposing)パターンも文書化されます MSDNで 。マネージリソースとアンマネージリソースの違いはありませんが、Disposeがコードによって呼び出されるのか、ランタイムによって呼び出されるのかは異なります。

1
Ben Hoffstein

IDisposeインターフェイスの正しい実装に関する良い記事を見つけました: http://msdn.Microsoft.com/en-us/library/ms244737(v = vs.80).aspx

0
OrahSoft

パブリックpublic void Dispose()protected virtual void Dispose(bool)、および~ClassName()ファイナライザを実装するパターンは、クリーンアップを適切に整理する方法として、ベストプラクティス Microsoftが推奨 です。マネージリソースとアンマネージリソースの両方のコード。

基本的に、Disposableクラスを使用するコードDispose()を呼び出す必要がありますが呼び出さない場合は、ファイナライザ~ClassName()を呼び出しますガベージコレクションによって呼び出され、それらのいずれが使用されるかに基づいて、引数をDispose(bool)にtrueまたはfalseとして設定し、Dispose(bool)でマネージリソースをクリーンアップするのは、引数は真です。

表示される警告では、ファイナライズメソッド~ClassName()でこの方法を使用することを特に推奨しているようです。

0
Sam Skuce