2016-08-03 3 views
-1

Dispose PatternはインターネットとSOFで広く議論されていますが、私の質問に答えるリソースは見つかりませんでした。ファイナライザが実装されていない場合、Dispose(bool)メソッドは必要ですか?

したがって、重複としてマークする前に最後まで読んでください。あなたが私が逃した以前の質問に私を向けることができれば、私は喜んで質問を削除します。


私はファイナライザを実装せずに(盲目的に)廃棄パターンを実装する多くのクラスを見てきました。

MSDN article on Dispose Patternは言う:

Booleanパラメータの処分は、法がIDisposable.Disposeの実装からか、ファイナライザから呼び出されたかどうかを示します。 Dispose(bool)実装は、他の参照オブジェクト(先のサンプルのリソースフィールドなど)にアクセスする前にパラメータをチェックする必要があります。このようなオブジェクトは、IDisposable.Dispose実装からメソッドが呼び出されたときにのみアクセスする必要があります(disposingパラメーターがtrueの場合)。 メソッドがファイナライザから呼び出された場合(disposingはfalseです)、他のオブジェクトにアクセスすべきではありません。その理由は、オブジェクトが予測不能な順序でファイナライズされるため、オブジェクトまたはそれらの依存関係のいずれかが既にファイナライズされている可能性があるからです。

私はGCが(実装されていれば)ファイナライザメソッドを呼び出し、Dispose(bool)メソッドをfalseとしてパラメータで呼び出す必要があると考えています。

私の最初の質問は、クラスがファイナライザを実装していない場合、Dispose(bool)がパラメータとしてfalseを呼び出すことですか? (例えば、CLRの何かによって私が出会っていないもの)

私は理解していますDispose(bool)は、オブジェクトが一度だけ廃棄されることを確認するために使用できます。

したがって、私の2番目の質問は、クラスがファイナライザを実装する必要がない場合、単に以下のようなDisposeメソッドを実装できるかどうかです。クラスは が廃棄(ブール値)これまでのように虚偽のパラメータで呼び出されるんその後、ファイナライザを実装していない場合

private bool objectDisposed; 
public void Dispose() 
{ 
    if (!objectDisposed) 
    { 
     // Release/dispose managed resources 
     // ... 
     // ... 

     objectDisposed = true; 
    } 
} 
+0

[廃棄上のこの広範な資料](https://web.archive.org/web/20051122090032/http:/ /www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae)すべての質問に回答します(編集:そこには書式設定があるので、ウェイバック版へのリンク) – stuartd

+0

[これには非常に関連しています質問.. 。](http://stackoverflow.com/questions/11024336/why-does-sealed-affect-the-implementation-of-idisposable) – spender

+0

私はすでに最初のものを読んだことありがとう。 – Menol

答えて

1

私の最初の質問はありますか? (例えば、私が遭遇していないCLRで何かによって )

NO

クラスは、その後 ファイナライザを実装する必要がない場合ので、私の2番目の質問があることができ、それは単に、以下の のようなDisposeメソッドを実装しますか?

私はしませんでした。そうするならば、このクラスが拡張されるなら、あなたはIDisposableパターンを再発明するでしょう。コメントにHansPassantが示すように、IDisposableパターンは派生クラスがあれば非常に便利です。私はむしろ最初の場所でそのパターンに従います。

基本クラス

using System; 

class BaseClass : IDisposable 
{ 
    // Flag: Has Dispose already been called? 
    bool disposed = false; 

    // Public implementation of Dispose pattern callable by consumers. 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this);   
    } 

    // Protected implementation of Dispose pattern. 
    protected virtual void Dispose(bool disposing) 
    { 
     if (disposed) 
     return; 

     if (disposing) { 
     // Free any other managed objects here. 
     // 
     } 

     // Free any unmanaged objects here. 
     // 
     disposed = true; 
    } 

    // Only if there are unmanaged resources. 
    ~BaseClass() 
    { 
     Dispose(false); 
    } 
} 

派生クラス

using System; 

class DerivedClass : BaseClass 
{ 
    // Flag: Has Dispose already been called? 
    bool disposed = false; 

    // Protected implementation of Dispose pattern. 
    protected override void Dispose(bool disposing) 
    { 
     if (disposed) 
     return; 

     if (disposing) { 
     // Free any other managed objects here. 
     // 
     } 

     // Free any unmanaged objects here. 
     // 
     disposed = true; 

     // Call the base class implementation. 
     base.Dispose(disposing); 
    } 

    // Only if there are unmanaged resources. 
    ~DerivedClass() 
    { 
     Dispose(false); 
    } 
} 
+0

それを拡張することはできません。 –

+0

私たちは本当にこの処分パターンを取り除かなければなりません。この答えは私たちがそこに行くのを助けるものではありません。新しいルール:もしあなたがクラスを封印していなければ**常にDispose()メソッドを仮想にします。 C++での標準規則btw。 –

関連する問題