1

在试图理解 IDisposable 时,我有几个问题大多数答案都没有明确说明。

  1. 如果我们在一个对象上调用 dispose,那是在那个时候释放这个对象还是只释放我们想要清理的类成员,并且整个对象稍后会被 GC 销毁。

  2. 我们在 dispose 方法中抑制 finalizer 后,GC 是否还会清理所有我们在 dispose 中没有清理的类成员?

4

4 回答 4

4

一旦对它的所有引用都消失了,就会以非确定性的方式对对象进行垃圾收集。 来自 MSDN 的垃圾收集: Garabge 收集基础

当下列条件之一为真时,就会发生垃圾收集:

  1. 系统物理内存不足。
  2. 托管堆上分配的对象使用的内存超过了可接受的阈值。这意味着已超过托管堆上可接受的内存使用量的阈值。随着流程的运行,此阈值会不断调整。

GC.Collect 方法被调用。在几乎所有情况下,您都不必调用此方法,因为垃圾收集器会持续运行。此方法主要用于特殊情况和测试。

  1. 垃圾收集何时使用
  2. 了解对象生命周期
于 2013-03-01T12:35:06.403 回答
2

首先,关于这个主题有很多重复的问题。如果真的没有其他答案明确回答您的问题,那么它们就是这样,但我希望这将作为重复关闭。

首先,Dispose只是一种方法,一种普通的方法。它根本不处理垃圾收集。

那么 Dispose 是做什么的呢?它应该用于清理非托管资源,例如文件句柄、窗口句柄等。.NET 垃圾收集器不知道的事情。

所以回答问题 1:“是的”,当你调用Dispose一个对象时,它会被放置在那里。类上没有设置标记以指示稍后进行清理。

由于 Dispose 不处理 Garbage Collection,因此您可以在 dispose 后轻松保留对对象的引用,并且不会被垃圾回收。垃圾回收仅在不再引用该对象时发生。即使您没有调用Dispose对象,这也可能发生,但不会发生,因为您调用Dispose了对象。

第二个问题:当 GC 在通过终结器循环后收集对象时,GC 将清理对象 + 它引用的任何不再有任何引用的对象(除了来自您的对象的引用)。这发生在某个时候,也不一定是同时发生的。

抑制终结器只是确保 GC 不会做不必要的工作,通过说“当你找到这个对象并确定它有资格收集时,继续收集它,我已经处理了'终结' 清理所以你不必“。

于 2013-03-01T12:40:51.923 回答
1

首先也是最重要的,您需要了解处理对象和垃圾收集对象是完全不同的事情——确保不要混淆两者!

  1. 如果我们在一个对象上调用 dispose,唯一发生的事情就是该Dispose方法被调用。可能是该Dispose方法然后继续调用GC.SuppressFinalize,但是它可能根本不做任何事情-它完全取决于实现。

  2. 当我们调用时GC.SuppressFinalize唯一发生的事情是它要求 GC 在收集对象时不要调用对象终结器(几乎就像对象一开始没有终结器一样)。

碰巧的是,一个常见的模式是让具有终结器的对象也实现IDisposable,以便可以确定性地清理非托管资源 - 如果发生这种情况,则 GC 不需要调用终结器,因为在当我们调用终结器时,已经执行了终结器Dispose——调用GC.SuppressFinalize只是对 GC 的友好提示,它实际上并不需要调用终结器。

于 2013-03-01T12:54:35.787 回答
0

1) 当您对一个对象调用 dispose 时,所发生的一切就是运行其 Dispose() 方法中的代码。这段代码当然可以为它的一个或多个字段调用 Dispose(),但这不是必须的。

它也可以调用基类' Dispose(true),如果有的话(通过base.Dispose()),但那是使用 Dispose Idiom; Dispose(bool)不是IDisposable界面的一部分。

2) 仅针对调用 SuppressFinalize() 的特定对象抑制终结器。它不会影响任何其他对象(包括调用 SuppressFinalize() 的对象的字段所持有的任何对象)。

于 2013-03-01T12:40:40.807 回答