4

讨论模式的指南/注释/文章都没有IDisposable建议应该nullDispose(bool)方法中设置内部成员(特别是如果它们是占用内存的野兽)。

在调试内部基准测试工具时,我开始意识到它的重要性。过去发生的事情是,这个缓冲区里面包含一个大数组。我们曾经为整个基准测试程序使用静态缓冲区。一旦我们完成了缓冲区,我们就无法释放这个内部数组,我们也不能让这个缓冲区可释放(因为它是静态的)。

所以,我相信,在Dispose()被调用之后,该类应该尽其所能释放它正在使用的所有资源并使它们再次可用,即使被处理的对象本身没有被 GC 回收,也没有设置成员为 null,因此,不允许 GC 收集内部对象意味着 Dispose 实现并不完美。

您对此有何看法?

4

3 回答 3

6

在此期间发布任何额外的引用Dispose肯定是我尝试做的事情,原因有两个:

  • 即使处置的对象仍在范围内,它也允许对内部对象进行垃圾收集
  • 如果内部对象是一次性的,这意味着即使Dispose()在外部对象上被重复调用,我们也只会处理一次

例如,我倾向于使用以下内容:

if(someDisposableObject != null)
{
    someDisposableObject.Dispose();
    someDisposableObject = null;
}
(for non-disposable, just set to null)
someNonDisposableObject = null; // etc

您可能还想将任何事件设置为 null:

someEventHandler = null;

如果调用者目前无法完全释放他们的引用(或只是忘记),这有助于将影响降至最低。虽然您应该尝试释放外部对象(对于 GC),但相对容易意外延长对象的生命周期,例如通过捕获的变量(匿名方法/lambda)、事件等。

如果您有终结器,那么在 GC 过程中这样做没有任何好处,并且您不应该真正调用外部对象(甚至Dispose())上的方法 - 所以简而言之:不要在 GC 扫描期间执行任何这些操作。

于 2009-01-19T05:01:27.810 回答
1

也许我错过了你的观点,但是一旦你的对象被释放,它相对于它的成员所代表的根或“子根”就被分离了。似乎您正在考虑像引用计数系统一样的垃圾收集(可以做到,但......通常不是)。

相反,将其视为一棵多根树,其中每个对象都有其链接到的分支。归根结底,“最终根”是静态变量以及从“主”循环中实例化的任何内容。

当垃圾收集器运行时,考虑它所做的最简单的方法是考虑它将遍历“真正的根”列表并将“颜色”应用于它可以“到达”的所有内容。

现在,假设收集器可以访问“所有内容”,无论它是否已植根。任何没有颜色的东西都可以清理干净。

回到您最初的问题,当您的对象被处置时,人们假设(或至少希望)没有人再引用它。如果是这种情况,它就不再有根,因此它不会有助于“着色”它所接触的任何东西。

长话短说 - 如果在 Dispose 例程中取消成员正在修复某些问题 - 我会是你有一个不同的,真实的问题,有人持有指向你的已处置对象的链接,并在不应该的时候保持它“可访问” .

我为这可能是我写过的最过度引用的信息道歉,但我有点滥用标准条款。

于 2009-01-19T04:59:45.893 回答
0

好吧,一般来说,这不会有什么不同。唯一会产生影响的地方是当您引用大对象堆上的对象时,您已经看到了该对象的行为)。

有一篇关于 LOH 的好文章在这里更详细地介绍了这一点:

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

于 2009-01-19T04:56:43.967 回答