web-dev-qa-db-ja.com

デストラクタはいつ作成する必要がありますか?

例えば:

public class Person
{
    public Person()
    {
    }

    ~Person()
    {
    }
}

デストラクタを手動で作成する必要があるのはいつですか?デストラクタを作成する必要があるのはいつですか?

172
delete

更新:この質問は 2015年5月の私のブログの主題 でした。すばらしい質問をありがとう!ファイナライズについて一般に信じられている偽りの長いリストについては、ブログを参照してください。

デストラクタを手動で作成する必要があるのはいつですか?

ほとんどは決してない。

通常、クラスが高価なアンマネージリソースを保持している場合にのみデストラクタを作成します。このリソースは、オブジェクトがなくなったときにクリーンアップする必要があります。リソースをクリーンアップするには、使い捨てパターンを使用することをお勧めします。デストラクタは本質的に、オブジェクトのコンシューマがオブジェクトの破棄を忘れた場合でも、リソースが最終的にクリーンアップされることを保証します。 (多分。)

デストラクタを作成する場合は、非常に注意してくださいおよびガベージコレクタの仕組みを理解してください。デストラクタは本当に奇妙です

  • それらはスレッド上では実行されません。それらは独自のスレッドで実行されます。デッドロックを引き起こさないでください!
  • デストラクタからスローされる未処理の例外は悪いニュースです。独自のスレッド上にあります。誰がそれを捕まえるのでしょうか?
  • オブジェクトに対してデストラクタを呼び出すことができますafterコンストラクタは開始しますが、beforeコンストラクターは終了します。適切に記述されたデストラクタは、コンストラクタで確立された不変式に依存しません。
  • デストラクタはオブジェクトを「復活」させ、死んだオブジェクトを再び生き返らせることができます。それは本当に奇妙です。しないでください。
  • デストラクタは実行されない場合があります。ファイナライズがスケジュールされているオブジェクトに依存することはできません。それはおそらくになりますが、それは保証ではありません。

デストラクタでは、通常真であるものはほとんどありません。本当に注意してください。正しいデストラクタを記述することは非常に困難です。

デストラクタを作成する必要があるのはいつですか?

デストラクタを処理するコンパイラの一部をテストするとき。実稼働コードでこれを行う必要はありませんでした。管理されていないリソースを操作するオブジェクトを書くことはめったにありません。

220
Eric Lippert

これは「ファイナライザー」と呼ばれ、通常、状態(フィールドなど)にアンマネージリソース(p/invoke呼び出しで取得したハンドルへのポインター)が含まれるクラスに対してのみ作成する必要があります。ただし、.NET 2.0以降では、管理されていないリソースのクリーンアップを処理するより良い方法があります: SafeHandle 。これを考えると、ファイナライザを再度書く必要はほとんどないはずです。

17
Nicole Calinoiu

クラスがWindowsファイルハンドルのような管理されていないリソースを保持していない限り、これは必要ありません。

8
John Saunders

デストラクタ/ファイナライザと呼ばれ、通常はDisposedパターンを実装するときに作成されます。

これは、クラスのユーザーがDisposeの呼び出しを忘れて(最終的に)リソースが解放されることを確認するフォールバックソリューションですが、デストラクタが呼び出されるタイミングについての保証はありません。

この Stack Overflow question では、受け入れられた回答は、処分パターンの実装方法を正しく示しています。これは、クラスに、ガベージコレクターがそれ自体をクリーンアップできない管理されていないリソースが含まれている場合にのみ必要です。

クラスのユーザーにリソースをすぐに解放するためにオブジェクトを手動で破棄する可能性も与えずに、ファイナライザを実装しないことをお勧めします。

3

管理されていないリソースがあり、オブジェクトがなくなったときにそれらがクリーンアップされることを確認する必要がある場合。良い例は、COMオブジェクトまたはファイルハンドラーです。

3
Vlad Bezden

WPFアプリケーションのスコープ内でメモリからオブジェクトがパージされているかどうかを確認するために、デストラクタ(デバッグ目的のみ)を使用しました。ガベージコレクションがオブジェクトをメモリから本当にパージしているかどうかはわかりませんでしたが、これは検証するのに良い方法でした。

2
Neil.Allen

デストラクタは、クラスにカプセル化されたアンマネージリソースを暗黙的に解放する方法を提供します。デストラクタは、GCに到達すると呼び出され、基本クラスのFinalizeメソッドを暗黙的に呼び出します。多くのアンマネージリソースを使用している場合、IDisposableインターフェイスを介してそれらのリソースを解放する明示的な方法を提供することをお勧めします。 C#プログラミングガイドを参照してください: http://msdn.Microsoft.com/en-us/library/66x5fx1b.aspx

0
SpaceghostAli