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 .NET Framework 中的自动内存管理

1) 如果一个类创建了一个一次性对象,它是否应该在它自己的 Dispose() 方法中对该对象调用 Dispose() 方法?

是的,它应该。否则,也会调用 Dispose。但这将使对象的寿命至少增加 1 代。这是由于类定义中的终结器。参考上面的文章链接。

2) 如果一次性对象作为引用传递给类,该类是否仍应调用该引用对象的 Dispose() 方法,还是应将其留给最初创建该对象的类?

调用者(更具体地说是创建实例的类)负责调用 Dispose 方法。

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

每当您发现自己在编写这样的代码时,请先深呼吸并问“我真的需要终结器吗?” 您需要一个非常罕见,仅当您自己拥有非托管资源时才需要终结器。

第一个试金石是“终结器真的了什么吗?” 如果您遵循代码,那就很清楚了。它调用 Dispose(false) 并且该代码仅在参数为真时才执行某些操作。接下来是您不需要终结器。这是完全正常的,终结器是微软担心的事情。他们编写了包装非托管资源的 .NET 框架类。文件流、套接字等。最重要的是,设计用于包装操作系统句柄的 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 回答