4

私はこのような質問についてSOを調べましたが、かなりの数を見つけたとしても、それらのどれもがこの問題に光を投げかけました。

私がこのコードを持っているとしましょう:

public class SuperObject : IDisposable
{
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing) { }
}
  • protected virtual void Dispose(bool)オンが必要SuperObjectですか? そこに処分するものは本当に何もないので。
public interface ICustom : IDisposable { }
public class Custom : ICustom
{
    public SuperObject Super { get; protected set; }

    public Custom()
    {
        Super = new SuperObject();
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public virtual void Dispose(bool disposing)
    {
        if (!disposing) return;

        if (Super != null)
            Super.Dispose();
    }
}
public class Foo
{
    public Foo()
    {
        using (var c = new Custom())
        {
            //do magic with c
        }
    }
}

IDisposable を既に実装し、実装しているCustomようなクラスで使用したい、使用する必要がある、または使用しようとするとどうなりますか?System.Web.Mvc.Controller

public class Moo : Controller
{
    Custom c;

    public Moo()
    {
        c = new Custom();
    }

    // Use c throughout this class        
}

で適切に処分するcにはMoo

4

2 に答える 2

9

通常のアプローチは、標準の IDisposable 実装を適用することです - ただし、これが実際に必要になるのは、クラスまたはそれから派生した一部のクラスが管理されていないリソースを使用する場合のみです -このケースは実際には非常にまれです(このケースが適用される場合は、ラップすることをお勧めします)完全な標準 IDisposable 実装を持つ独自のクラスのアンマネージ リソース)。

したがって、管理されていないリソース (生のファイル ハンドル、グローバルに割り当てられたメモリなど) を扱っておらず、破棄可能なメンバー (つまり、管理されたリソースを持ち、IDisposable を実装している) のみを扱っていると仮定すると、最小限の実装で安全に方法を得ることができますIDispose - つまり:

void Dispose() メソッドを 1 つだけ用意します。そのメソッドでは、dispoable メンバーで dispose を呼び出してから、使い捨ての場合は基本クラスで Dispose を呼び出します。クラス階層がある場合は、この Dispose を仮想化しても問題ありません。Dispose(bool) メソッドを持つ必要はありません。また、オブジェクトが破棄されているかどうかを確認する必要もありません。これは、他のオブジェクトで dipsose を呼び出すだけであり、それらの実装がその確認を行うためです。

最小限のアプローチが気に入らない場合は、標準の完全な実装を適用してください (ただし、厳密には必要ではありません)。つまり、推奨されるアプローチに従うためのスティックラーであるため、標準の実装を行うか、単純な最小限の(しかし正しい)実装を行います-ただし、その間に何かをしないでください(つまり、標準ではない、単純ではない、または正しくない)!

詳細については、この質問を参照してください:管理対象リソースのみに対する最小限の IDispose 実装

したがって、あなたの場合、以下は最小限の実装です。

public class SuperObject : IDisposable {
    public void Dispose() {
        // Dispose code...just call dispose on dispoable members.
        // If there are none then no need to implement IDisposable!
    }
}

public interface ICustom : IDisposable { }
public class Custom : ICustom {
    public SuperObject Super { get; protected set; }

    public Custom() {
        Super = new SuperObject();
    }

    public void Dispose() {
        if (Super != null)
            Super.Dispose();
    }
}  

public class Moo : Controller {
    Custom c;

    public Moo() {
        c = new Custom();
    }

    public Dispose() {
        if (c!=null)
            c.Dispose()
        base.Dispose();       
    }
}

スーパー オブジェクトに破棄可能なリソースがない場合は、IDisposable を実装して Dispose メソッドを使用しても意味がないことに注意してください。税関の唯一の使い捨てオブジェクトが SuperObject である場合、同じことが適用され、同じロジックが Moo に適用されます。最後に、上記のすべてが当てはまり、他に使い捨てオブジェクトがない場合、本当に必要なものは次のとおりです。

  public class Moo : Controller {
        Custom c;
    
        public Moo() {
            c = new Custom();
        }
    
        public Dispose() {
           base.Dispose();       
        }
    }
于 2013-09-29T09:56:14.537 に答える
3

で適切に処分するcにはMoo

public class Moo : Controller
{
    Custom c;

    public Moo()
    {
        c = new Custom();
    }

    // Use c throughout this class    


    protected override Dispose(bool disposing)
    {
        base.Dispose(disposing);
        if (disposing)
           c.Dispose()
    }
}

また、それはあなたの最初の質問にも答えます。ControllerそのDispose(bool)方法を作成する必要がprotected virtualあるか、上記は不可能です。

ただし、いくつかの注意事項:

  • isDisposedあなたには論理がありません。破棄は 1 回だけ行うことをお勧めします。また、破棄後の使用法をトラップすることもできます。
  • デストラクタ (ファイナライザ) を省略すること自体は良い考えですが、派生クラスがアンマネージリソースを所有してはならないという追加の制約があります。
于 2013-09-29T09:21:09.127 に答える