在处理之前清除收集的重要性是什么

时间:2016-09-20 05:02:08

标签: c# collections memory-leaks dispose clear

以下代码之间有什么区别

代码1:

if(RecordCollections!=null){
   RecordCollections.Clear();
   RecordCollections=null;
}

代码2:

RecordCollections = null;

代码存在于Dispose方法中,在将Collection设置为null之前,使用Clear方法有什么优势吗?是否需要它?

2 个答案:

答案 0 :(得分:3)

  

在将Collection设置为null之前,使用Clear方法是否有任何优势。

没有好的Minimal, Complete, and Verifiable code example就不能说。

那就是说,这些代码片段对我来说都不是很有用。如果Clear()方法所做的只是清空集合,那么第一个肯定是毫无意义的。当然,如果它真的经历过,例如在每个集合成员上调用Dispose(),这将是不同的。但这将是一个非常不寻常的集合实现。

即使是第二个也没有什么价值,并且与正常的IDisposable语义相反。 IDisposable应该仅用于管理非托管资源。它有时用于其他事情,但这是它的主要目的。特别是,通常只在丢弃对象之前调用Dispose()。如果对象本身将被丢弃,那么它将保留给其他对象(例如集合)的任何引用将不再可访问,因此将它们设置为null并没有任何有用的效果。

事实上,在某些情况下,将变量设置为null实际上可以扩展对象的生命周期。运行时非常复杂,可以识别变量不再使用,如果它保留了对象的最后一个剩余引用,则该对象可以在该点符合垃圾收集条件,即使变量的范围进一步扩展。通过将变量设置为null,变量本身将在稍后的程序中使用,因此运行时不能将其视为无法访问,直到该点为止,晚于其他方式。

最后一点通常最常用于局部变量,而不是对象中的字段。但从理论上讲,运行时可以更广泛地进行优化。这是一个不好的习惯,进入设置null变量,这些变量本身不会更长。

答案 1 :(得分:1)

Dispose是指明确清理un-managed memory的机制,因为无法使用标准Garbage Collector清除,大多数IDisposable将由类实施,它在内部使用非托管API,如Database Connection

标准做法是:

  • 同时实现Finalizer,因为Dispose是一个显式调用,如果被调用者遗漏,那么Finalization确实会处理清理操作,尽管它需要2个循环的GC

  • 如果一个类使用任何一个对象,作为一个实现Dispose本身的类变量,那么应该实现Dispose来调用类变量上的Dispose。 / p>

关于提供的代码:

if(RecordCollections!=null){
   RecordCollections.Clear();
   RecordCollections=null;
}

或者

RecordCollections = null;

由于这与清理托管内存有关,因此GC执行主要工作并且不需要它,但是在我看来它是acceptable practice,其中类变量显式无效,这使得用户改变每个分配,并且主要是尝试使用方法局部变量,直到除非状态需要在方法调用之间共享。对象分配滥用,可以更加严格控制。

就差异而言,虽然集合被明确清除然后无效或只是无效,但内存保持不变,直到调用点GC,即un-deterministic,但在我的查看它不是很清楚,如果一个对象被明确标记为{{GC,那么null如何显式地映射要收集的对象,这些对象不再可达,但对于各代,尤其是较高代的(升级对象)。 1}},然后GC可能需要花费更少/没有时间来跟踪根/引用,但是没有明确的文档来解释这个方面/实现。