我对实现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),但我似乎无法找到正确的结构方法的具体例子。
答案 0 :(得分:2)
请参阅优秀的MSDN文章 Garbage Collection: Automatic Memory Management in the Microsoft .NET Framework
1)如果一个类创建了一个一次性对象,它应该在自己的Dispose()方法中调用该对象上的Dispose()方法吗?
是的,应该。否则,也会调用Dispose。但这会增加至少1代对象的生命。这是由于类定义中的终结器。请参阅上面的文章链接。
2)如果一个一次性对象作为引用传递给一个类,那么该类是否仍然在该引用对象上调用Dispose()方法,还是应该将它留给创建该对象的类?
调用者(更具体地说是创建实例的类)负责调用Dispose方法。
答案 1 :(得分:1)
~Bar() {
Dispose(false);
}
每当你发现自己编写这样的代码时,先深呼吸并问“我真的需要终结者吗?”您需要一个极为罕见,只有在您自己拥有非托管资源时才需要终结器。
第一个试金石是“终结者真的做什么?”如果您遵循代码,那就很清楚了。它调用Dispose(false),并且该代码仅在参数为true时执行某些操作。接下来是不需要终结器。这是完全正常的,终结者是微软所担心的。他们编写了包装非托管资源的.NET框架类。 FileStream,Socket等。最重要的是,SafeHandle类,旨在包装操作系统句柄。他们有自己的终结者,你不要自己重写。
因此,如果没有终结器,代码将完全折叠为简单而正确的实现,您只需要调用自己存储的任何一次性对象的Dispose()方法:
public class Bar : IDisposable {
private readonly Foo MyFoo;
public Bar() {
this.MyFoo = new Foo();
}
public void Dispose() {
MyFoo.Dispose();
}
}