3

IDisposableを実装する正しい方法について、私はいくつかのしつこい疑問を持っています。次のシナリオを考えてみましょう...

public class Foo : IDisposable {...}

public class Bar : IDisposable {

    private bool disposed = false;
    private readonly Foo MyFoo;

    public Bar() {
        this.MyFoo = new Foo();
    }
    public Bar(Foo foo) {
        this.MyFoo = foo;
    }
    ~Bar() {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing) {
        if (!this.disposed) {
            if (disposing) {
               if (MyFoo != null) {
                   this.MyFoo.Dispose();
                   this.MyFoo = null;
               }
            }
            this.disposed = true;
        }
    }

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

私の質問は次のとおりです。

1)クラスが使い捨てオブジェクトを作成する場合、そのオブジェクトに対して独自のDispose()メソッドでDispose()メソッドを呼び出す必要がありますか?

2)使い捨てオブジェクトが参照としてクラスに渡された場合、そのクラスは引き続きその参照オブジェクトに対してDispose()メソッドを呼び出す必要がありますか、それとも最初にオブジェクトを作成したクラスに任せる必要がありますか?

上記のパターンは(特にDIで)かなり多く発生するようですが、これを構造化する正しい方法の具体的な例を見つけることができないようです。

4

2 に答える 2

2

優れたMSDNの記事「 ガベージコレクション:Microsoft.NETFrameworkでの自動メモリ管理」を参照してください。

1)クラスが使い捨てオブジェクトを作成する場合、そのオブジェクトに対して独自のDispose()メソッドでDispose()メソッドを呼び出す必要がありますか?

はい、そうすべきです。それ以外の場合も、Disposeが呼び出されます。しかし、それは少なくとも1世代までオブジェクトの寿命を延ばします。これは、クラス定義のファイナライザーによるものです。上記の記事のリンクを参照してください。

2)使い捨てオブジェクトが参照としてクラスに渡された場合、そのクラスは引き続きその参照オブジェクトに対してDispose()メソッドを呼び出す必要がありますか、それとも最初にオブジェクトを作成したクラスに任せる必要がありますか?

Disposeメソッドを呼び出すのは、呼び出し元(より具体的にはインスタンスを作成したクラス)の責任です。

于 2012-11-26T11:41:14.860 に答える
1
~Bar() {
    Dispose(false);
}

このようなコードを書いていることに気付いたときは、まず深呼吸して、「実際にファイナライザーが必要ですか?」と尋ねてください。ファイナライザーが必要になることは非常にまれです。ファイナライザーが必要になるのは、管理されていないリソースの所有権を自分で取得する場合のみです。

最初のリトマス試験は「ファイナライザーは実際に何かをするのか」です。あなたがコードに従うならば、それは明らかです。Dispose(false)を呼び出し、そのコードは引数がtrueの場合にのみ何かを実行します。次のことは、ファイナライザーは必要ないということです。これは完全に正常なことであり、ファイナライザーはMicrosoftが心配していることです。彼らは、管理されていないリソースをラップする.NETFrameworkクラスを作成しました。FileStream、Socketなど。そして何よりも、オペレーティングシステムのハンドルをラップするように設計されたSafeHandleクラス。彼らは独自のファイナライザーを持っています、あなたはそれを自分で書き直さないでください。

したがって、ファイナライザーがないと、コードは完全に単純で正しい実装に崩壊します。自分で保存した使い捨てオブジェクトのDispose()メソッドを呼び出すだけで済みます。

public class Bar : IDisposable {
    private readonly Foo MyFoo;
    public Bar() {
        this.MyFoo = new Foo();
    }
    public void Dispose() {
        MyFoo.Dispose();
    }
}
于 2012-11-26T12:15:01.493 に答える