讨论IDisposable
模式的指南/注释/文章都没有提出应该在null
方法中将内部成员设置为Dispose(bool)
(特别是如果它们是记忆占用的野兽)
我在调试内部基准测试工具时已经意识到它的重要性。过去常见的是,这个缓冲区内部包含一个大数组。我们过去常常为整个基准程序使用静态缓冲区。一旦我们完成了缓冲区,我们就无法释放这个内部数组,也不能让这个缓冲区可释放(因为它是静态的)。
所以,我相信,在调用Dispose()
之后,类应该尽其所能,以便它释放它正在使用的所有资源并使它们再次可用,即使被处置的对象不是由GC收集,而不是将成员设置为null,因此,不允许GC收集内部对象意味着Dispose实现并不完美。
您对此有何看法?
答案 0 :(得分: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扫描期间的这一点。
答案 1 :(得分:1)
也许我错过了你的观点,但是一旦你的对象被处理掉了,它所代表的根或“子根”就已经被分离了。看起来你正在考虑垃圾收集,就像一个引用计数系统(可以这样做,但通常不会)。
相反,将其视为一个多根树,其中每个对象都有链接到它的链接。在一天结束时,“最终根”是静态的,并且从“主”循环中实例化。
当垃圾收集器运行时,考虑它的作用的最简单方法是考虑它将走“真正的根”列表并对它可以“到达”的所有内容应用“颜色”。
现在,假设收藏家可以访问“一切”,无论它是否已根。任何没有着色的东西都可以清理干净。
回到原来的问题,当你的对象被处置时,人们会假设(或者至少希望)没有人再引用它。如果是这种情况,它就不再有根,所以它不会有助于“着色”它所触及的任何东西。
长篇故事 - 如果在Dispose例程中清空成员正在修复某些东西 - 我会遇到一个不同的,真实的问题,即有人持有指向您已处置对象的链接,并保持其“可达”状态不应该。
我为可能是我写过的最引用率最高的消息道歉,但我有点滥用标准条款。
答案 2 :(得分:0)
嗯,一般来说,它不会有所作为。唯一可以产生影响的地方是当你有一个对象时,你已经看到了大对象堆上的一个对象。
关于LOH的文章很好,这里有更详细的内容: