2011-11-22 11 views
6

基本的に私は次のようになり、いくつかの機能があります:私はすべての機能に代わりに別のもの[インスタンス]の同じリソースを使用することができます仮定の下すべての関数でステートメントを使用する - >適切なクリーンアップでクラスフィールドに変換する?

class MyClass 
{ 
    void foo() 
    { 
     using (SomeHelper helper = CreateHelper()) 
     { 
      // Do some stuff with the helper 
     } 
    } 

    void bar() 
    { 
     using (SomeHelper helper = CreateHelper()) 
     { 
      // Do some stuff with the helper 
     } 
    } 
} 

はそれがクリーンアップに関してでOKの練習で、このようにする?

class MyClass 
{ 
    SomeHelper helper = CreateHelper(); 

    // ...foo and bar that now just use the class helper.... 

    ~MyClass() 
    { 
     helper.Dispose(); 
    } 
} 
+2

代わりのあなたの代わりにファイナライザを使用した可能性が(可能であれば) 'MyClass'で' IDisposable'を実装し、コールを廃棄するときは、 'helper.Dispose' –

答えて

8

いいえ、ではありません。デストラクタ(Finalizer)を追加してください。

リソースを再利用できますが、クラスはIDisposableを実装する必要があります。

sealed class MyClass : IDisposable 
{ 
    SomeHelper helper = CreateHelper(); 

    // ...foo and bar that now just use the class helper.... 

    //~MyClass() 
    public void Dispose()  
    { 
     helper.Dispose(); 
    }       
} 

これで、使用ブロックでMyClassインスタンスを使用する必要があります。自己は管理リソースになりました。

デストラクタは使用されません。MyClassインスタンスが収集されるときはいつでも、関連付けられたヘルパーオブジェクトは同じコレクション内にあります。しかし、デストラクタを持つことは、依然として相当なオーバーヘッドを招く。

IDisposableのstandard patternvirtual void Dispose(bool disposing)メソッドを使用しますが、クラスsealedを作成するときには上記の最小限の実装を使用できます。

+0

は、理由の説明と私はトラブルあなたのだろうか? (私はあなたの答えによってデストラクタが悪い考えであると仮定しています) –

+0

はい、デストラクタは高価で無駄です。編集されました。 –

+0

また、ファイナライザは特に動作することが予想される動作を微妙に破ることができる(特にC#のファイナライザがC++のデストラクタに似ていないことが原因です)、いつでも呼び出すことが保証されていません。 –

1

あなたはそれがあなたimplement IDisposableことが推奨されている場合には、オブジェクトの有効期間中に、このようなリソースを共有することができます。

1

クラスがIDisposableオブジェクトを所有している場合は、IDisposableも実装する必要があります。だから、ファイナライザを実装するのではなく、クラスにIDisposableを実装し、そのヘルパーのdiposeを実装する必要があります。

ファイナライザを実装する際の1つの問題は、呼び出されるタイミングを制御できないことです。使い捨てパターンは、リソースをクリーンアップするためのより決定論的な方法を提供します。

1

いいえ、そうではありません。ファイナライズされたものがいつ廃止されるかはわかりません。また、あなたのリソースが管理されている場合、そのリソースは最終段階で何らかの時点で廃棄されます。

いつも使用したくない場合は、たぶん多くの機能で一度使用することができます。

2

.NET you don't know when (or whether) finalizer is calledでは、まったく同じです。私は再取得していないhelperを確保するためにreadonlyを使用

class MyClass : IDisposable 
{ 
    readonly SomeHelper helper = CreateHelper(); 

    // any method can use helper 

    public void Dispose() 
    { 
     helper.Dispose(); 
    } 
} 

using(var myObj = new MyClass()) { 
    // at the end, myObj.Dispose() will trigger helper.Dispose() 
} 

(これはSomeHelperはまったく同じものです)

代わりに、を明示的にクラスがimplementing IDisposableによってに処分されるべきであることを示しますクラス内の他の場所に割り当てられていますが、これは本当に重要です。

nullに設定しないでください、またはDisposeが例外をスローするように注意する必要があります。フィールドがprotectedの場合は、Disposeを呼び出して安全にプレーしていることを知ることができます。

1

オブジェクト内のファイナライザをオーバーライドする必要はありません。これは、2番目のコードサンプルに~MyClass()で示されています。

IDisposableパターンを実装する必要があります。管理対象リソースとアンマネージリソースを使用している場合は、あなたの質問に明白ではありませんが、管理対象リソースのクイックサンプルがあります。 Stackoverflowにはこれに関する数多くの例があります。 Reed Copseyにも良いシリーズがあり、hereを始めることができます。

class MyClass : IDisposable 
{ 
    private bool _Disposed; 
    private SomeHelper _Helper; 
    protected virtual void Dispose() 
    { 
     this.Dispose(true); 
    } 
    public void Dispose(bool disposing) 
    { 
    if (_!Disposed && disposing) 
    { 
     if (_Helper != null) 
      _Helper.Dispose(); 
     _Disposed = true; 
    } 
    } 
} 
関連する問題