web-dev-qa-db-ja.com

C#では、クラスのデストラクタとFinalizeメソッドの違いは何ですか?

クラスのデストラクタとFinalizeメソッドの違いはありますか?

最近、Visual Studio 2008は、Finalizeメソッドと同義のデストラクタを考慮することを発見しました。つまり、Visual Studioでは、クラスで両方のメソッドを同時に定義することはできません。

たとえば、次のコードフラグメント:

class TestFinalize
{
    ~TestFinalize()
    {
        Finalize();
    }

    public bool Finalize()
    {
        return true;
    }
}

デストラクタでFinalizeを呼び出すと、次のエラーが発生します。

次のメソッドまたはプロパティ間で呼び出しがあいまいです: 'TestFinalize。〜TestFinalize()'および 'TestFinalize.Finalize()'

また、Finalizeの呼び出しがコメント化されている場合、次のエラーが発生します。

タイプ「ManagementConcepts.Service.TestFinalize」は、同じパラメータータイプで「Finalize」というメンバーを既に定義しています

88
Jeff Leonard

C#のデストラクタは_System.Object.Finalize_メソッドをオーバーライドします。あなたはそうするためにデストラクタ構文を使用する必要がありますFinalizeを手動でオーバーライドすると、エラーメッセージが表示されます。

基本的にFinalizeメソッドの宣言でやろうとしていることは、 hiding 基本クラスのメソッドです。これにより、コンパイラはnew修飾子を使用して黙らせることができる警告を発行します(動作する場合)。ここで注意すべき重要なことは、同じ名前のoverrideメンバーとnewメンバーの両方を宣言できないことです同時に、デストラクタとFinalizeメソッドの両方を使用するとエラーが発生します(ただし、canは推奨されませんが、デストラクタを宣言していない場合は、public new void Finalize()メソッドを宣言します)。

62
Mehrdad Afshari

ウィキペディアには、 finalizer 記事のファイナライザーと デストラクタ の違いについての良い議論があります。

C#には「真の」デストラクタはありません。構文はC++デストラクタに似ていますが、実際にはファイナライザです。例の最初の部分で正しく書きました。

~ClassName() { }

上記はFinalize関数の構文糖衣です。ベースのファイナライザの実行が保証されますが、それ以外はFinalize関数のオーバーライドと同じです。これは、デストラクタ構文を記述するとき、実際にファイナライザを記述することを意味します。

Microsoftによると 、ファイナライザはガベージコレクタが収集するときに呼び出す関数(Finalize)を参照しますが、デストラクタは結果として実行されるコードの一部です(構文Finalizeになる砂糖。それらは同じものに非常に近いので、Microsoftは決して区別するべきではありませんでした。

C++ではオブジェクトが削除またはスタックからポップされるとすぐに同じスレッドで実行されるのに対し、C#では別のスレッドで実行されるため、MicrosoftによるC++の「デストラクタ」という用語の使用は誤解を招きます。

65
Kenzi

ここにあります:http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. デストラクタ

    これらは、オブジェクトのクリーンアップコードを含む特別なメソッドです。 GCによって暗黙的に呼び出されるため、コード内で明示的に呼び出すことはできません。 C#では、~記号が前に付いたクラス名と同じ名前になります。いいね

    Class MyClass
    {
    
    ~MyClass()
    {
    .....
    }
    }
    

    VB.NETでは、デストラクタはSystem.ObjectクラスのFinalizeメソッドをオーバーライドすることにより実装されます。

  2. 廃棄する

    これらはクラスの他のメソッドと同様であり、明示的に呼び出すことができますが、オブジェクトをクリーンアップするという特別な目的があります。 disposeメソッドでは、オブジェクトのクリーンアップコードを記述します。データベース接続やファイルなどのdisposeメソッドのアンマネージリソースをすべて解放することが重要です。disposeメソッドを実装するクラスは、IDisposableインターフェイスを実装する必要があります。Disposeメソッドは、破棄するオブジェクトのGC.SuppressFinalizeメソッドを呼び出すクラスにはオブジェクトをクリーンアップする作業が既に行われているため、クラスにはデストラクターがあり、ガベージコレクターがオブジェクトのFinalizeメソッドを呼び出す必要はありません。参照: http://msdn2.Microsoft.com/en-us/library/aa720161(VS.71).aspx

  3. ファイナライズ

    Finalizeメソッドは、Disposeメソッドが呼び出されない場合にリソースをクリーンアップするためのセーフガードとして機能します。管理されていないリソースをクリーンアップするには、Finalizeメソッドのみを実装する必要があります。ガベージコレクターは管理対象リソースを自動的にクリーンアップするため、管理対象オブジェクトにはFinalizeメソッドを実装しないでください。 FinalizeメソッドはGCによって暗黙的に呼び出されるため、コードから呼び出すことはできません。

    注:C#では、Finalizeメソッドはオーバーライドできないため、MSILのFinalizeメソッドをオーバーライドする内部実装を持つデストラクタを使用する必要がありますが、 VB.NET、Finalizeメソッドは、デストラクタメソッドをサポートしているため、オーバーライドできます。

更新:興味深い半関連スレッドはこちら .

19
Andrew Siemer