【问题标题】:Garbage collection, and dispose questions. Appreciate some brainy assistance垃圾收集,并处理问题。感谢一些聪明的帮助
【发布时间】:2013-12-19 16:09:24
【问题描述】:

Dispose 方法是否使用垃圾收集器来清除资源?
使用 Dispose 代替终结器还有什么好处吗?
我已经搜索了答案,但到目前为止还没有什么能很好地解释它。
谢谢你。

【问题讨论】:

标签: c# object garbage-collection dispose finalizer


【解决方案1】:

Dispose() 是一个常规方法。
它与垃圾收集器无关。

Dispose() 这样的调用方法允许您释放垃圾收集器不知道的非托管资源,例如本机文件句柄。
你也应该在终结器中这样做,这样如果你的调用者忘记调用Dispose(),它们就不会泄漏。但是,调用Dispose() 可以立即释放它们,而不是等待垃圾收集器处理您的对象。

如果您的对象包含其他具有非托管资源的对象,您应该实现Dispose(),而不是终结器。 Dispose() 允许您的调用者立即处理更深层次的非托管资源,但您没有任何事情需要终结者做。 (非托管资源应该由内部终结器释放)

要清楚地实现这一点,请使用Dispose(disposing) pattern,它清楚地描述了在何处处置托管和非托管资源。

【讨论】:

  • 所以你基本上是说我应该只使用 Dispose () 而不是 GC,因为我没有真正的理由来实现 GC? GC 会自动实现。
  • 正确。实施正确的模式,GC 会自行处理。
  • @EPOColla:你根本无法实现 GC 或与 GC 交互。
  • 感谢您帮助我理解。但是 gc.collect 呢?那不是和 GC 交互吗?
【解决方案2】:

dispose()方法是否使用垃圾回收清理资源?

没有。 Dispose() 用于释放非托管资源(通常)。它与GC没有任何关系。

见:IDisposable interface

这个接口的主要用途是释放非托管 资源。垃圾收集器自动释放内存 当不再使用该对象时分配给该对象。 但是,无法预测垃圾收集何时会 发生。此外,垃圾收集器不知道 非托管资源,例如窗口句柄或打开的文件和流。

垃圾收集器调用对象的终结器(析构函数),如果该对象实现IDisposable,那么终结器可以调用Dispose(false)

【讨论】:

  • 感谢您的回复。所以我应该总是自动选择使用而不是终结器,因为垃圾收集应该是自动化的?
  • @EPOColla,如果一个对象实现了IDisposable,那么将它与using一起使用或调用Dispose释放非托管资源,except Task class
  • 我现在才知道 GC 更适用于非托管资源,所以现在更有意义了。如果用于托管资源,我可能没有理由使用 Finalizer。谢谢
  • @EPOColla,no GC 用于托管资源,IDisposable 接口或 Dispose Pattern 用于释放非托管资源。垃圾收集器不能/不会对非托管资源做任何事情。
  • 当我可以使用 using 时,我有什么理由必须调用 GC.Collect() 吗?谢谢。
【解决方案3】:

一些对象,为了按照指定的行为,需要外部实体代表他们做事。在某些情况下,外部实体将能够在方法返回之前执行所有必要的操作。然而,在其他情况下,一个方法需要在要求外部实体继续做某事直到另行通知(但没有给它这样的通知)之后返回。因此,对象有责任让外部实体知道何时不再需要其服务。

IDisposable 的目的是提供一种标准化的方式,通过该方式可以告诉对象“不再需要您的服务,因此,如果您已要求任何外部实体开始代表您做某事,那么您可以反过来用它来满足你的客户,你应该告诉他们停止这样做。”它通常不会释放任何内存(除非外部实体保留了一些内存来帮助它满足对象的需求),并且在许多情况下实际上不需要做任何事情(如果没有外部实体代表某些人做任何事情)对象,无需告知任何人停止代表其行事)。

终结器的存在主要是为了处理实现IDisposable 的对象可能在没有调用其 dispose 方法的情况下被放弃的可能性。它有效地告诉一个对象“看起来你已经被遗弃了,所以你应该清理一下”。尽管 Finalize 可以充当“安全网”,但不应认为它是可靠的;通常,如果一个具有终结器的对象被错误地放弃,终结器将在“某个时候”运行,但通常不能保证及时性。因此,当不再需要请求实体代表它做某事的对象时,应该立即告知(通过Dispose)而不是放弃它。在正确编写的程序中,很少有终结器应该运行。

【讨论】:

    【解决方案4】:

    这里有很多关于释放非托管资源的答案——这确实是 Dispose 的一个角色。 但需要注意的是,这种情况(必须处理原始托管资源,即操作系统文件句柄、套接字句柄等)非常罕见。在几乎所有情况下,我们都通过 MANAGED 对象处理这些资源 -他们自己实现 IDisposable 来释放他们的资源。
    因此,实际上编写 dispose 的常见原因不是什么资源被释放,而是什么时候资源被释放。也就是说,一般来说,我们编写 Dispose 是因为我们的对象包含控制资源的(托管)成员(例如,保持打开套接字的 TCPClient)。通过实现 IDispose,我们允许我们类的用户控制何时释放 MANAGED 资源 - 通过应用 using 语句或通过显式调用 Dispose

    【讨论】:

      猜你喜欢
      • 2011-10-12
      • 1970-01-01
      • 1970-01-01
      • 2011-04-06
      • 1970-01-01
      • 1970-01-01
      • 2011-02-23
      • 2011-06-03
      • 1970-01-01
      相关资源
      最近更新 更多