2009-07-02 19 views
74

デストラクタとクラス内のFinalizeメソッドの間に違いがありますか?C#では、クラスのデストラクタとFinalizeメソッドの違いは何ですか?

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

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

    public bool Finalize() 
    { 
     return true; 
    } 
} 

デストラクタに完成させるためにコールに次のエラーを与える:たとえば、以下のコードフラグメントは

完成させるために呼び出しがコメントアウトされている場合

The call is ambiguous between the following methods or properties: 'TestFinalize.~TestFinalize()' and 'TestFinalize.Finalize()'

そして、それは次のエラーが発生します。

Type 'ManagementConcepts.Service.TestFinalize' already defines a member called 'Finalize' with the same parameter types

答えて

52

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

基本的に、Finalizeメソッド宣言で何をしようとしているのかは、基本クラスのメソッドhidingです。コンパイラは、new修飾子(動作する場合)を使用してサイレントにすることができる警告を出します。ここで注意すべき重要なことはあるが、あなたが両方overrideとはとてもデストラクタとエラーになりますFinalize方法の両方を有すると同時に、同じ名前を持つnewメンバーを宣言することはできません(ただし、をできるということです推奨しない場合は、デストラクタを宣言していない場合はpublic new void Finalize()メソッドを宣言してください)。

16

Found here: http://sanjaysainitech.blogspot.com/2007/06/difference-between-destructor-dispose.html

  1. Destructor

    They are special methods that contains clean up code for the object. You can not call them explicitly in your code as they are called implicitly by GC. In C# they have same name as the class name preceded by the ~ sign. Like-

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

    In VB.NET, destructors are implemented by overriding the Finalize method of the System.Object class.

  2. Dispose

    These are just like any other methods in the class and can be called explicitly but they have a special purpose of cleaning up the object. In the dispose method we write clean up code for the object. It is important that we freed up all the unmanaged recources in the dispose method like database connection, files etc. The class implementing dispose method should implement IDisposable interface.A Dispose method should call the GC.SuppressFinalize method for the object it is disposing if the class has desturctor because it has already done the work to clean up the object, then it is not necessary for the garbage collector to call the object's Finalize method. Reference: http://msdn2.microsoft.com/en-us/library/aa720161(VS.71).aspx

  3. Finalize

    A Finalize method acts as a safeguard to clean up resources in the event that your Dispose method is not called. You should only implement a Finalize method to clean up unmanaged resources. You should not implement a Finalize method for managed objects, because the garbage collector cleans up managed resources automatically. Finalize method is called by the GC implicitly therefore you can not call it from your code.

    Note: In C#, Finalize method can not be override, so you have to use destructor whose internal implementation will override the Finalize method in MSIL.But in the VB.NET, Finalize method can be override because it does support destructor method.

更新:Interesting semi-related thread here

+0

'管理していないリソースをクリーンアップするためのFinalizeメソッドのみを実装する必要があります:Finalizeに入れます。 Disposeと同じですか? – hqt

+0

@ hqt:ファイナライザを実装すべき場所よりも「Dispose」を大幅に上回らなければならないケースをはるかに上回ります。クラスまたは派生クラスのインスタンスがアンマネージリソースを直接所有するか、直接アンマネージリソースを直接所有するかを直接所有するか、直接最後のものを直接所有する可能性が高い場合は、Disposeを実装します自分のクラスがの場合は、直接がアンマネージリソースを所有していて、それ以外のものはほとんどありません。 - はるかに狭いシナリオです。 – supercat

+0

@hqt:クラスが直接アンマネージリソースを所有し、他のオブジェクトへの参照を保持している場合、アンマネージドリソースは一般に、自分自身のファイナライズ可能なクラスに分割する必要があります。他のオブジェクトへの参照を保持するクラスは、リソース自体を所有するのではなく、「管理されていないリソースを直接所有するもの」を所有するだけで、ファイナライザは必要ありません。 – supercat

50

ウィキペディアは、ファイナライザととの相違点について、finalizerの記事でよく議論しています。

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

~ClassName() { } 

以上がFinalize関数のシンタックスシュガーです。これは、ベース内のファイナライザが確実に動作することを保証しますが、それ以外の場合はFinalize関数をオーバーライドすることと同じです。つまり、デストラクタ構文を記述すると、実際にファイナライザが作成されます。デストラクタは、結果(Finalizeなる糖衣構文)として実行されるコードのあなたのビットである

According to Microsoft、ファイナライザは、それが収集したときに、ガベージコレクタが呼び出す関数(Finalize)を指します。彼らは、マイクロソフトが一度も区別してはならないのと同じことに非常に近い。

マイクロソフトではC++の「デストラクタ」という用語を誤解しています。なぜならC++ではオブジェクトが削除されたりスタックからポップされたりするとすぐに同じスレッドで実行されるからです。別の時間。

+0

私は、デストラクタとファイナライザの間のこのような区別は重要なものであると主張します。しかし、フードの下で起こっていることを気にする人だけが、この区別に気をつけます。 –

+0

また、ECMA-334はずっと前に正式に "デストラクタ"と "ファイナライザ"を明確に明確にしています。私はなぜMSが依然として仕様の誤解を招く言葉を主張しているのか分かりません。 – FrankHB

+0

少なくともMonoを使っているので、C#はC++の後に実際にモデル化されています。ほとんどのネイティブC#オブジェクトはC++オブジェクトです。 Monoの作品をコンパイルするコンパイラは、それらのC++オブジェクトがどのように破壊されるかを指示し、同様にC#オブジェクトのファイナライズをC++に伝播させ、そのデストラクタを呼び出します。 区別はボンネットの下では意味がありますが、C#自体にはまだ実際には当てはまりません。 – Kenzi

関連する問題