我有一个对象,其中包含一次性对象作为成员。
public class MyClass
{
private MyDisposableMember member;
public DoSomething
{
using (member = new MyDisposableMember())
{
// Blah...
}
}
}
MyClass
中可以有很多方法,所有方法都需要using
语句。但如果我这样做呢?
public class MyClass
{
private MyDisposableMember member = new MyDisposableMember();
public DoSomething
{
// Do things with member :)
}
~MyClass()
{
member.Dispose();
}
}
如您所见,
member
正在析构函数中被处置。这行得通吗?这种方法有什么问题吗?
理想情况下,Dispose() 应该在最终确定之前被调用。最好遵循典型的 dispose 模式,并允许用户正确 Dispose() 对象,并让终结器对其进行 Dispose 如果 dispose 尚未被调用。
在这种情况下,由于您封装了 IDisposable,因此您实际上根本不需要实现终结器。 (在最终确定时,您的封装成员将被最终确定,因此无需最终确定您的对象 - 它只会增加开销。)有关详细信息,请阅读我写的关于封装 IDisposable 的博客文章。
MyClass
实现
IDisposable
。在
Dispose()
方法内,调用
member.Dispose();
。这样程序员就可以控制成员何时被处置。
GC 将为您执行此操作(间接作为要处置的对象或另一个对象将包含析构函数)
MyDisposableMember 甚至可能在您处置它之前就被 GC 处置 - 然后发生的事情可能不是您想要做的。
更糟糕的是:在类中添加析构函数(或终结器)会在处理对象时花费额外的时间(因为对象将在内存中保留至少一个收集周期,甚至可能提升到下一代),因此会花费更多时间。
那么,就完全没有用,甚至适得其反。
更一般地说,您应该将所有处理逻辑放在 Dispose() 中并实现 IDisposable,然后将您的类与 using 或 try-finally 一起使用
public class MyClass : IDisposable
{
private MyDisposableMember member = new MyDisposableMember();
public DoSomething
{
// Do things with member :)
}
~MyClass()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing) // Release managed resources
{
member.Dispose();
}
// Release unmanaged resources
}
}
IDisposable
对象,以下任一情况都成立:
Dispose
至多是无用的。
Dispose
将毫无用处。
Dispose
会很糟糕。
Dispose
可能会很有用,但大多数情况都符合上面列出的情况,这些情况都有一个共同的特征:终结器不应调用
Dispose
。