如果.NET有垃圾回收,为什么你还需要显式调用IDisposable
?
如果.NET有垃圾回收,为什么你还需要显式调用IDisposable
?
垃圾回收是针对内存的。你需要处理非内存资源 - 文件句柄,套接字,GDI+句柄,数据库连接等。这通常是 IDisposable
类型的基础,尽管实际的句柄可能深藏在一系列引用中。例如,您可能会 Dispose
一个 XmlWriter
,它会释放它所引用的 StreamWriter
,后者会释放 FileStream
本身持有的文件句柄。
在其他评论的基础上再扩展一下:
Dispose()方法应该被调用来处理所有具有非托管资源引用的对象。这些对象的例子包括文件流、数据库连接等。一个基本规则是:“如果.NET对象实现了IDisposable,那么当你使用完对象后应该调用Dispose()。”
然而,还有一些需要注意的事项:
除非绝对必要,否则不要在自己的对象中实现IDisposable。实现不良或不必要的实现可能会使情况变得更糟。一些好的指导可以在这里找到:
Finalize()
而非Dispose()
。 - Greg DIDisposable
的目的是提供一种标准方式,让对象知道它们的服务不再需要时。这反过来允许它们通知其他对象,它们曾经使用过这些对象的服务,这些其他对象的服务也不再需要了。关心其服务何时不再需要的对象应该实现 IDisposable
。拥有关心自己何时不再需要的其他对象的对象也应该实现 IDisposable
,以便将“不再需要”的通知转发给这些内部对象。 - supercat由于对象有时会持有除内存之外的资源,GC会释放内存;IDisposable则是为了释放其他任何资源。
因为您想要控制对象持有的资源何时被清理。
看,垃圾回收机制是有效的,但它只会在自己感觉需要的时候才进行,即使这样,您添加到对象中的终结器也只会在2次垃圾回收后才被调用。有时,您希望立即清理这些对象。
这就是IDisposable的用途。通过显式调用Dispose()(或使用using块的语法糖),您可以以标准方式访问对象并使其自我清理(例如,您可以实现自己的cleanup()调用并显式调用它)
您希望立即清理的示例资源包括:数据库句柄、文件句柄、网络句柄。
IDisposable
接口通常在资源方面进行描述,但是大多数这样的描述未能真正考虑到"资源"的真正含义。
有些对象需要向外部实体提出请求,以便代表它们执行某项操作,直到另行通知为止,这可能会对其他实体造成不利影响。例如,一个包含文件流的对象可能需要向文件系统(可以位于连接的宇宙中的任何地方)请求对文件的独占访问权。在许多情况下,对象对外部实体的需求将与外部代码对对象的需求相关联。例如,一旦客户端代码完成了与上述文件流对象相关的所有操作,该对象就不再需要对其关联的文件具有独占访问权(或者根本不需要访问该文件)。
一般来说,请求实体执行某项任务直到另行通知的对象X会产生交付此类通知的义务,但只要X的客户端可能需要X的服务,就无法交付此类通知。IDisposable的目的是提供一种统一的方式,让对象知道它们的服务将不再需要,以便它们可以通知代表它们行事的实体(如果有的话)它们的服务不再需要。调用IDisposable的代码既不需要知道也不需要关心对象从外部实体请求了什么(如果有的话)服务,因为IDisposable仅邀请对象履行对外部实体(如果有的话)的义务。