public void Dispose(){ ... }
如何处理释放任何未受管控的资源?
是什么?
protected virtual void Dispose(bool disposing){ ... }
总是必要的、有时必要的,还是完全不必要的?
public void Dispose(){ ... }
如何处理释放任何未受管控的资源?
是什么?
protected virtual void Dispose(bool disposing){ ... }
总是必要的、有时必要的,还是完全不必要的?
完整的模式包括终结器、引入新的虚拟方法以及"封口"原始dispose方法,非常通用,覆盖所有基础。
除非你有对非托管资源的直接句柄(几乎从不),否则你不需要终结器。
如果你封口了你的类(而我对于尽可能封口类的看法可能已经广为人知 - 为继承设计或禁止它),那么引入虚拟方法就没有意义了。
我不记得上一次是以"复杂"的方式实现IDisposable
还是以最明显的方式实现它了,例如:
public void Dispose()
{
somethingElse.Dispose();
}
需要注意的一点是,如果你想要编写非常健壮的代码,应该确保在被销毁后不再执行任何操作,并在适当的情况下抛出ObjectDisposedException
。这是给全世界的开发者使用的类库的好建议,但如果仅在自己的工作区中使用,则为了获得很少的收益而付出了很多的努力。
这不是必须的。它是推荐的可清除模式的一部分。如果您还没有阅读过《框架设计指南》中关于此问题的章节(第一版的9.3,很抱歉没有第二版的资料),那么建议您先阅读。尝试这个链接。
将可清除的清理和需要进行终结器垃圾回收区分开来非常有用。
您不一定非得按照这种方式去做,但在将其视为不必要之前,建议您先了解为什么推荐这样做,并阅读相关内容。
微软文档中有一些关于可释放模式的偏见。有两个原因你应该实现IDisposable:
第1种情况在大多数代码中非常普遍。第2种情况在微软编写的代码中非常普遍,他们编写了管理封装非托管资源的代码,这些代码需要进行终止处理。但在你的代码中这种情况应该非常罕见。毕竟,你有所有这些好用的.NET类来为你完成繁琐的工作。你只需要调用它们的Dispose()方法即可。
只有第2种情况需要使用可释放模式。Microsoft需要经常使用它。而你大部分时间只需要简单的Dispose()方法。
除了其他优秀的答案外,您可能还想查看以下文章:
带有bool disposing参数的附加方法是从某个框架设计指南中提出的。这仅仅是一种模式,允许您的类拥有dispose方法可以被多次调用而不会抛出异常。它并非绝对必要。从技术上讲,您可以在dispose方法中完成此操作。
仅仅是为了扩展其他人所说的:不仅是你不需要“复杂的处理”,而且出于性能原因,你实际上不想要它。
如果你选择“复杂的处理”路线,并实现一个终结器,然后忘记显式地处理你的对象,那么你的对象(以及它引用的任何内容)将在真正处理之前多存活一代GC(因为它必须再多挂一次等CLR调用终结器)。这只会造成更多不必要的内存压力。此外,对整个堆中的对象调用终结器具有非微不足道的成本。
因此,除非你(或你的派生类型)拥有非托管资源,否则请避免使用“复杂的处理”。
哦,在我们讨论这个问题时:你类中处理来自其他类的事件的方法必须在该类被处理后被调用时“安全”。最简单的方法是,如果该类已被处理,则执行无操作。请参见http://blogs.msdn.com/ericlippert/archive/2009/04/29/events-and-races.aspx。
它给你的一个好处是能够在Dispose()中执行与终结无关的工作,同时清理非托管资源。
在终结器中对托管对象进行任何操作都是极其不可预测的,除了对自己的操作。这主要是因为你的终结器将在AppDomain的第二阶段关闭时以非确定性的方式被调用,所以当你的终结器被调用时,你仍然有引用的对象很可能已经被终结了。
将Dispose和终结器调用分派到同一个方法中允许你共享关闭代码,而布尔参数允许你跳过托管清理(如果有的话)。
此外,该方法的虚拟性提供了一种简单的方式,使得继承者可以添加自己的清理代码,而不会意外地忘记调用你的代码。
IDisposable.Dispose()
方法,而派生类需要添加额外的逻辑,那么该类必须公开某种Dispose
方法,以便派生类可以链接到该方法。由于一些类可能会实现IDisposable.Dispose()
方法而没有公共的Dispose()
方法,因此有一个虚拟方法是很有用的,该方法将在所有IDisposable
实现中都被保护,无论它们是否具有公共的Dispose
方法。在大多数情况下,bool
参数并不真正有意义,但应该将其视为虚拟方法protected virtual Dispose(bool)
与可能是或可能不是公共的Dispose()
具有不同的签名。
没有使用protected virtual Dispose(bool)
的类将要求派生类以与约定不同的方式处理其清理逻辑。一些语言(如C++/CLI)只能扩展遵循该约定的IDisposable
实现,可能无法从非标准实现派生类。