有不同的有效用途
IDisposable
。一个简单的例子是持有打开的文件,你需要在某个时刻关闭它,只要你不再需要它了。当然,你可以提供一个方法
Close
,但在
Dispose
内使用
using (var f = new MyFile(path)) { /*process it*/ }
这样的模式会更可靠避免异常。
一个更流行的例子是持有其他一些需要释放的IDisposable
资源,这通常意味着您需要提供自己的Dispose
以便将它们释放。
通常,只要您想要确定性地销毁任何东西,您就需要实现IDisposable
。
我的观点与你的观点不同,在我看来只有当某种资源需要确定性的销毁/释放时,我才会实现IDisposable
,而不是尽快实现。在这种情况下,依赖垃圾回收并不是一个选择(与你的同事的说法相反),因为它发生在不可预测的时间,并且实际上可能根本不会发生!
任何资源都是不受管理的事实并没有什么意义:开发人员应该考虑“何时以及如何释放此对象”而不是“它在底层如何工作”。底层实现可能随时间变化而改变。
事实上,C#和C ++之间的主要区别之一是缺少默认的确定性销毁。 IDisposable
填补了这个空缺:您可以命令确定性销毁(尽管您不能确保客户端调用它;同样,在C ++中,您无法确保客户端调用delete
)。
小补充:确定性释放资源与尽快释放资源之间实际上有什么区别? 实际上,这些是不同的(尽管并非完全正交的)概念。
如果要
确定地释放资源,这意味着客户端代码应该有可能说“现在我想释放这个资源”。这实际上可能不是资源可以被释放的
最早时间:持有资源的对象可能已经从资源中获取了所有需要的内容,因此它可能已经自行释放了该资源。另一方面,该对象可能选择保留(通常未受管理的)资源,即使在对象的
Dispose
方法运行后,只在终结器中清理它(如果长时间持有资源不会产生任何问题)。
所以,为了尽快释放资源,严格来说,并不需要
Dispose
方法:一旦它自己意识到不再需要该资源,对象就可以立即释放该资源。然而,
Dispose
方法提供了一个有用的提示,即对象
本身不再需要,因此如果合适的话,
可能会在那时释放资源。
还有一个必要的补充:并不只有未受管理的资源需要确定性地分配!这似乎是答案之间观点差异的关键之一。人们可以构建纯想象的结构,这些结构可能需要确定性地释放。
例如:访问某些共享结构的权限(考虑
RW-lock),大量存储器块(想象一下你手动管理程序的一些内存),许可证可使用其他程序(想象一下你不允许同时运行
X个某个程序副本),等等。在这里,要释放的对象不是未受管理的资源,而是做/使用某些东西的
权利,这是纯粹的程序逻辑内部构建。
小小的补充:这里有一些巧妙地滥用IDisposable
的示例列表:http://www.introtorx.com/Content/v1.0.10621.0/03_LifetimeManagement.html#IDisposable。
IDisposable
的唯一另一个场合,是在处理非托管资源之外,当我需要确保事件被正确取消订阅以便类可以被垃圾回收时。但这实际上是语言的缺陷:事件真的真的 非常 需要弱引用,但它们并没有。 - BlueRaja - Danny Pflughoeft