29

この答えで私が見つけた、

コードで Dispose/Finalize パターンが使用されている場合は、Finalize メソッドでアンマネージド リソースをクリーンアップし、Dispose メソッドでマネージド リソースをクリーンアップします。

その後、ファイナライズと破棄に関するこの素晴らしい記事を見つけて、それらについて明確なアイデアを得ました。この記事には、概念を説明する次のコード (ページ 3 ) があります。

class Test : IDisposable
{
    private bool isDisposed = false;

    ~Test()
    {
       Dispose(false);
    }

    protected void Dispose(bool disposing)
    {
       if (disposing)
       {
          // Code to dispose the managed resources of the class
       }
       // Code to dispose the un-managed resources of the class

       isDisposed = true;
    }

    public void Dispose()
    {
       Dispose(true);
       GC.SuppressFinalize(this);
    }
}

しかし、その下には、同じメモ (この質問の冒頭に含めたもの) が表示されます。

Dispose/Finalize パターン アンマネージ リソースを操作する場合は、Dispose と Finalize の両方を実装することをお勧めします。正しいシーケンスは、開発者が Dispose を呼び出すことです。開発者が Dispose メソッドを明示的に呼び出すことを怠った場合でも、オブジェクトがガベージ コレクションされると、Finalize 実装が実行され、リソースが引き続き解放されます。Francesco Balena はブログで次のように書いています。「Dispose/Finalize パターンは、型がアンマネージド リソース (アンマネージド メモリを含む) を割り当てるアンマネージド コードを呼び出し、最終的にリソースを解放するために使用する必要があるハンドルを返す場合にのみ使用する必要があります。破棄とファイナライズの両方が必要です。自身のメンバーを破棄またはファイナライズした後に、親のそれぞれのメソッドを呼び出して、親オブジェクトに連鎖します。」 簡単に言えば、コードで Dispose/Finalize パターンが使用されている場合は、Finalize メソッドでアンマネージド リソースをクリーンアップし、Dispose メソッドでマネージド リソースをクリーンアップします。

今、私は再び混乱しています。記事全体とコード サンプルでは、​​管理されていないリソースを .NET で解放する必要があることが示されていDispose()ます。しかし、そのコメントの関連性は何ですか?

編集:

この行が確認されているので:

簡単に言えば、コードで Dispose/Finalize パターンが使用されている場合、Finalize メソッドでアンマネージド リソースをクリーンアップし、Dispose メソッドでマネージド リソースをクリーンアップします。

は間違っています。この回答を編集しました。

4

2 に答える 2

52

とてもシンプルです。

  1. 管理されていないリソースを扱っている場合Dispose- と の両方を実装しFinalizeます。Dispose開発者は、リソースが不要になったことを確認したらすぐにリソースを解放するために呼び出します。呼び出しを忘れた場合Dispose、フレームワークは独自の GC サイクルでファイナライズを呼び出します (通常、独自の甘い時間がかかります)。
  2. オブジェクトが使い捨てオブジェクトを内部で使用している場合- 実装し、まだ破棄していないDispose()タイプのオブジェクトへの参照を作成して保持している場合は、実装Dispose()します。
  3. 上記のいずれにも当てはまらない場合 (アンマネージ リソースを扱っておらず、オブジェクトが内部で使い捨てオブジェクトを使用していない場合) - 何もしないでください。実装しFinalizeないでくださいDispose

いくつかの古典的な例:

System.IO.FileStreamオブジェクトは、ファイルへのロック/ストリーム ハンドルを管理します。したがって、dispose と finalize の両方を実装します。開発者がそれを破棄すると、他のプログラムがすぐにアクセスできます。彼がそれを破棄するのを忘れた場合、フレームワークはそれをファイナライズし、GC サイクルの後半でハンドルを閉じます。

System.Text.StringBuilder管理されていないリソースはありません。したがって、処分もファイナライズもありません。

パターンに関する限り、それは何を意味するのか

// Code to dispose the managed resources of the class

そのクラス内のコンポーネントとして持っている.NETオブジェクトのDisposeメソッドを呼び出すことです

// Code to dispose the un-managed resources of the class

生のハンドルとポインターを閉じることを意味します。例を含む更新されたコードは次のとおりです

class Test : IDisposable
{
  private bool isDisposed = false;

  ~Test()
  {
    Dispose(false);
  }

  protected void Dispose(bool disposing)
  {
    if (!isDisposed)
    {
      if (disposing)
      {
        // Code to dispose the managed resources of the class
        internalComponent1.Dispose();
        internalComponent2.Dispose();
      }

      // Code to dispose the un-managed resources of the class
      CloseHandle(handle);
      handle = IntPtr.Zero;   

      isDisposed = true;
    }
  }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }
}

これはそれを説明する古い質問です

于 2013-05-17T05:31:00.880 に答える