如果.NET有垃圾收集那么为什么你必须显式调用 IDisposable?

有帮助吗?

解决方案

垃圾收集用于记忆。您需要处理非内存资源 - 文件句柄,套接字,GDI +句柄,数据库连接等。这通常是 IDisposable 类型的基础,尽管实际句柄可能在链条上相当长的路径参考文献。例如,你可以 Dispose 一个 XmlWriter ,它配置一个 StreamWriter 它有一个引用,它处理 FileStream it 有一个引用,它会释放文件句柄本身。

其他提示

对其他评论进行一些扩展:

应在所有引用非托管资源的对象上调用 Dispose() 方法。此类示例包括文件流、数据库连接等。大多数时候有效的基本规则是:“如果 .NET 对象实现了 IDisposable,那么您应该在使用完该对象后调用 Dispose()。

但是,还需要记住其他一些事项:

  • 调用 dispose 并不能让您控制何时实际销毁对象并释放内存。GC 为我们处理这个问题并且比我们做得更好。
  • 正如 Jon 所指出的,Dispose 会清理所有本机资源,一直到基类堆栈。然后它调用 SuppressFinalize() 来指示该对象已准备好被回收,不需要进一步的工作。GC 的下一次运行将清理它。
  • 如果没有调用Dispose,那么GC会发现需要清理的对象,但必须先调用Finalize,以确保资源被释放,对Finalize的请求会排队,GC继续进行,因此缺少一个调用 Dispose 会强制再运行一次 GC,然后才能清理对象。这会导致对象被提升到下一代 GC。这看起来似乎没什么大不了的,但在内存压力较大的应用程序中,将对象提升到更高代的 GC 可能会将高内存应用程序推向内存不足的应用程序。
  • 除非绝对需要,否则不要在自己的对象中实现 IDisposable。实施不当或不必要的实施实际上会使事情变得更糟而不是更好。可以在这里找到一些好的指导:

    实现 Dispose 方法

    或者阅读 MSDN 关于垃圾收集的整个部分

因为对象有时会在内存旁边保留资源。 GC释放内存; IDisposable是你可以释放任何其他东西。

因为您希望控制对象保留的资源何时清理。

请参阅,GC可以工作,但是当它感觉到时,它会这样做,即使这样,添加到对象的终结器也只能在2个GC集合之后被调用。有时,您希望立即清理这些对象。

这是使用IDisposable的时候。通过显式调用Dispose()(或使用using块的thr语法糖),您可以访问您的对象以标准方式清理自己(即您可以实现自己的cleanup()调用并显式调用它)

您希望立即清理的示例资源包括:数据库句柄,文件句柄,网络句柄。

为了使用using关键字,对象必须实现IDisposable。 http://msdn.microsoft.com/en-us /library/yh598w02(VS.71).aspx

IDisposable 界面通常根据资源来描述,但大多数此类描述未能真正考虑什么是“资源”。真的意思是。

有些对象需要要求外部实体代表他们做某事,而不利于其他实体,直到另行通知为止。例如,包含文件流的对象可能需要询问文件系统(可以是连接的Universe中的任何位置)以授予对文件的独占访问权。在许多情况下,对象对外部实体的需求将与外部代码对对象的需求联系在一起。一旦客户端代码完成了与上述文件流对象相关的所有操作,例如,该对象将不再需要对其关联文件进行独占访问(或任何访问)。

一般而言,要求实体做某事直到另行通知的对象X才有义务提供此类通知,但只要X的客户可能需要X的服务,就无法发出此类通知。 IDisposable 的目的是提供一种统一的方式让对象知道他们的服务将不再需要,以便他们可以通知代表他们的实体(如果有的话)他们的服务不再需要。调用 IDisposable 的代码既不需要知道也不关心对象从外部实体请求的服务(如果有的话),因为 IDisposable 只是邀请一个对象履行义务(如果任何)到外部实体。

要根据“资源”进行处理,当对象要求外部实体代表其执行某些操作时(通常,但不一定,授予对某些内容的独占使用),对象获取资源,直到另行通知为止当资源告诉外部实体不再需要其服务时。获取资源的代码不会获得“事物”。它承担了一项义务;释放资源不会放弃“事物”,而是履行义务。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top