【问题标题】:What is IDisposable for?IDisposable 有什么用途?
【发布时间】:2009-03-05 14:53:21
【问题描述】:

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

【问题讨论】:

  • 如果您将 IDisposable 放在搜索框中,这个问题已有很多答案。

标签: c# garbage-collection dispose idisposable


【解决方案1】:

垃圾收集是为了内存。您需要处理非内存资源 - 文件句柄、套接字、GDI+ 句柄、数据库连接等。这通常是 IDisposable 类型的基础,尽管实际句柄在引用链中可能有很长的路要走。例如,您可能会在 DisposeXmlWriter 中处理它所引用的 StreamWriter,它会处理 FileStream 所引用的引用,从而释放文件句柄本身。

【讨论】:

    【解决方案2】:

    在其他 cmets 上扩展一点:

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

    不过,还有一些需要注意的事项:

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

      Implementing a Dispose Method

      Or read that whole section of MSDN on Garbage Collection

    【讨论】:

    • Re: “不要实现 IDisposable ... 除非你绝对需要” - 定义接口时要小心 - 如果接口的实现可能需要处理,那么接口应该从一开始就可以抛弃。否则所有客户端都需要重构。
    • +1 以获得更好和更彻底的答案。我怀疑除非你必须,否则不要实施某些东西的警告更多地针对Finalize()而不是Dispose()
    • IDisposable 的目的是提供一种标准方法,让对象知道何时不再需要其服务。这反过来又允许他们通知他们一直在使用其服务的其他对象不再需要那些其他对象的服务。不再需要服务时关心的对象应实现IDisposable。拥有其他关心何时不再需要的对象的对象同样应该实现IDisposable,这样它们就可以将“不再需要”的通知转发给那些内部对象。
    【解决方案3】:

    因为对象有时会在内存之外拥有资源。 GC释放内存; IDisposable 是为了让你可以释放其他任何东西。

    【讨论】:

      【解决方案4】:

      因为您想控制对象持有的资源何时被清理。

      看,GC 可以工作,但它会在需要的时候这样做,即使这样,您添加到对象中的终结器也只会在 2 次 GC 收集后被调用。有时,您想立即清理这些对象。

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

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          IDisposable 接口经常用资源来描述,但大多数这样的描述并没有真正考虑到“资源”的真正含义。

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

          一般来说,要求实体做某事直到另行通知的对象 X 会产生传递此类通知的义务,但只要 X 的客户可能需要 X 的服务,就不能传递此类通知。 IDisposable 的目的是提供一种统一的方式让对象知道不再需要他们的服务,以便他们可以通知代表他们行事的实体(如果有)他们的不再需要服务。调用IDisposable 的代码既不需要知道也不需要关心对象向外部实体请求了什么(如果有)服务,因为IDisposable 只是邀请对象履行对外部实体的义务(如果有)。

          用“资源”来表述事物,当一个对象请求外部实体代表它做某事(通常,但不一定,授予某事物的独占使用权)直到另行通知时,一个对象获取了一个资源,并释放了一个当它告诉外部实体不再需要它的服务时,资源。获取资源的代码不会获得“东西”,而是会产生义务;释放资源并不是放弃“事物”,而是履行了一项义务。

          【讨论】:

            猜你喜欢
            • 2011-07-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-04-13
            • 2012-01-13
            • 2011-09-20
            • 2019-04-16
            • 2016-01-23
            相关资源
            最近更新 更多