1

に関してでIDisposable

ほとんどの場合、システム リソースを使用すると予想されるインターフェイスを作成していますが、常にではありません。IDisposable使用法が私のインターフェイスに含まれていると予想するのは賢明でしょうか?

たとえば、同期する手段を提供するインターフェイスがあります。

interface IDateTimeProvider : IDisposable
{
    int LeapSeconds {get;set;}
    DateTime LocalNow {get;}
    DateTime UtcNow {get;}
    DateTime GpsNow {get;}
}

class NtpTimeProvider : IDateTimeProvider
{
    // Assume client is setup and ready to use.
    // Obtains time via network resources
    NtpClient client;  

   NtpTimeProvider (int leapSeconds)
   { LeapSeconds = leapSeconds;}

    int LeapSeconds {get;set;}
    DateTime LocalNow {get{return client.Utc};}
    DateTime UtcNow {get{return client.Utc};}
    DateTime GpsNow {get{return client.Utc - TimeSpan.FronSeconds(LeapSeconds);}}
    void Dispose()
    {
        if(client != null) Client.Dispose();
    }
}


class SystemTimeProvider : IDateTimeProvider
{

   SystemTimeProvider (int leapSeconds)
   { LeapSeconds = leapSeconds;}

    int LeapSeconds {get;set;}
    DateTime LocalNow {get{return DateTime.Now};}
    DateTime UtcNow {get{return DateTime.UtcNow };}
    DateTime GpsNow {get{return DateTime.UtcNow - TimeSpan.FronSeconds(LeapSeconds);}}
    void Dispose()
    { //obviously this isn't needed}
}

問題は、IDisposableほとんどの実装が解放する必要のあるシステム リソースを使用すると予想される場合に、要件を課す必要があるかどうかです。IDateTimeProvider のユーザーがリソースを解放し、

if(myDateTimeProvider is IDisposable) ((IDisposable)myDateTimeProvider).Dispose();

必要ないでしょう。

4

3 に答える 3

1

50,000 ドルの問題は、特定の型を知らずにインターフェイスを実装するオブジェクトの所有権をコードが取得するかどうか、およびクリーンアップが必要かどうかです。これが発生する可能性がある状況では [最も一般的な例はIEnumerable.GetEnumerator()IEnumerable<T>.GetEnumerator()ですが、他にも多くの例が存在します]、クライアント コードは次の 2 つのパターンのいずれかを使用する必要があります。

  • インターフェイス型が実装されていないIDisposable場合 [non-genericIEnumeratorによって返される非ジェネリックの場合のようにIEnumerable]、オブジェクトの所有権を取得した適切に記述されたクライアント コードは、オブジェクトを放棄する前に、特定のオブジェクトがインターフェースを実装するIDisposableと、たまたま実装され、そうであれば、その実装を呼び出しますIDisposable.Dispose

  • インターフェイスが を実装する場合、IDisposable所有権を取得した適切に作成されたクライアントは、オブジェクトを放棄する前にIDisposable.Dispose、オブジェクトが実際にクリーンアップを必要としないことを何らかの方法で認識していない限り、オブジェクトを呼び出す必要があります。オブジェクトがそのメソッドで何もしない場合でもIDisposable.Dispose、多くの場合、呼び出しが必要かどうかを判断するのにかなりの時間を費やすよりも、無条件に呼び出す方が速いことに注意してください。オブジェクト インスタンスの 0.001% のみがクリーンアップを必要とする場合IDisposableでも、クライアント コードに新しい義務を与えることはありません。むしろ、クライアント コードが義務を果たす可能性が高くなり、すべてのオブジェクトのコストが削減されます。インスタンスの 99.999% はクリーンアップを必要としません。

インターフェイスがファクトリ メソッドによって返されたり、オブジェクトの所有者がクリーンアップが必要かどうかわからない他のシナリオで使用されたりする可能性が低い場合は、インターフェイスに を実装する必要はありませんIDisposable。ただし、ファクトリ メソッドによってインターフェイス タイプが返される可能性がある場合は、 を実装する必要がありますIDisposable

于 2013-04-01T17:12:09.143 に答える
1

一般に、インターフェースを提供する理由は、プログラマーが概念のさまざまな実装を同じ一連の動作を持つものとして扱えるようにするためです。システム リソースを管理するクラスだけに実装IDisposableすると、プログラマーはその実装の詳細に対処する必要があり、設計が複雑で脆弱になります。

オブジェクトの有効期限が切れたときにアンマネージド リソースがアプリケーションによって参照される可能性がある場合はIDisposable、クラスのコンシューマーが Dispose パターンを使用してそれらのリソースを予測可能な方法で解放できるように、インターフェイスを絶対に実装する必要があります。

破棄パターンの理由についてのリマインダーとして:

コンピューター プログラミングでは、破棄パターンは、自動ガベージ コレクションを使用するランタイム環境でリソースのクリーンアップを処理するために使用される設計パターンです。Dispose パターンが解決しようとしている基本的な問題は、ガベージ コレクション環境のオブジェクトにはデストラクタではなくファイナライザがあるため、決定論的な時点でオブジェクトが破棄されるという保証がないということです。Dispose パターンは、オブジェクトが保持しているすべてのリソースを解放するメソッド (通常は Dispose などと呼ばれます) をオブジェクトに与えることで、これを回避します。

http://en.wikipedia.org/wiki/Dispose_pattern

于 2013-03-29T16:16:31.047 に答える
1

問題は、ほとんどの実装が解放する必要があるシステム リソースを使用すると予想される場合、IDisposable 要件を課す必要があるかどうかです。

これには議論の余地がありますが、フレームワークにはこのガイドラインに従う例があります。良い例はStreamIDisposableです -これが必要でないサブクラスがあっても実装します。

ただし、一部のユーザーだけでなく、ほぼすべての実装で が必要になることが本当に確実でない限り、ユーザーにこれを要求することについては注意が必要ですIDisposable

于 2013-03-29T16:16:40.510 に答える