让C#垃圾收集列表而不是重用它是不好的形式?

时间:2012-07-18 18:50:37

标签: c# list garbage-collection

我有一个稳定增长的元素列表,直到我将该列表中的所有数据转储到文件中。然后,我想再次将该列表重用于同一目的。简单地将其分配给新列表而不是从列表中删除所有元素是不好的做法吗?似乎垃圾收集应该处理旧列表,这样我就不必担心删除元素了。

例如:

var myList = new List<element>();
myList.Add(someElement);
myList.Add(anotherElement);
// dumps the elements into a file

myList = new List<element>();

编辑:即使有很简单的方法,我也想知道它的哲学方面。如果周围有办法让垃圾收集起来是不是很糟糕?允许垃圾收集与删除元素和重用相同内存的成本是多少?

6 个答案:

答案 0 :(得分:6)

myList.Clear()myList = new List<element>();

更容易编码

msdn: List.Clear Method

列表中的每个元素本身都是不同的对象,无论是清除列表,还是重新创建新列表,或者一次删除一个项目,都需要进行垃圾回收。如果您只是清除列表并重复使用它就不需要进行垃圾回收是列表本身。除非您的列表很大,包含数十万个项目,否则很难以某种方式衡量性能差异。幸运的是,垃圾收集器经过高度优化,在开发人员需要考虑它正在做什么的情况下很少见。

(正如其他人所指出的那样,涉及到各种因素,例如......你将在新列表中添加多少元素?vs旧​​列表中有多少元素?...但重点是:当收集列表的元素时,列表本身的垃圾收集不相关。)

答案 1 :(得分:6)

这取决于列表中有多少元素。如果支持列表的阵列足够大,可以在大对象堆上,那么最好清除列表并重新使用它。这将减少大内存分配的数量,并将有助于减少大对象堆碎片的问题。 (有关详细信息,请参阅http://msdn.microsoft.com/en-us/magazine/cc534993.aspxhttp://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/;有关.NET 4.5的改进,请参阅http://blogs.msdn.com/b/dotnet/archive/2011/10/04/large-object-heap-improvements-in-net-4-5.aspx

如果列表较小,您可能最好只创建一个新列表,或者调用Clear()可能会获得更好的性能。如有疑问,请测量性能。

编辑:为了回应您在编辑中提出的哲学问题,创建新列表有两个原因:

  1. 通常,如果不重用对象,代码会更清晰,更容易推理。垃圾收集的成本很低,代码混乱的成本很高。
  2. 考虑如果转储列表内容的代码在另一个函数中会发生什么,因为它很可能是。一旦将该列表从其本地上下文中传出,就可能存在对同一列表的非本地引用。其他代码可能正在修改列表,或者可能假设(错误地)您没有修改它。

答案 2 :(得分:1)

我不是专家,但是:
制作一个新的列表,期望GC会“照顾”旧的,这可能是一个的想法,因为这是一个不好的做法&amp;可能效率低下 虽然这是微观优化,但我会说“设置”新值直到达到list.Count,并且继续list.Add是最好的方法,因为那样你就不会清除也不会分配不必要的新内存(除非你希望清空空间的大型列表)
无论如何,我建议使用List.Clear() - 它可以节省你和GC的麻烦。

答案 3 :(得分:1)

听起来你问的是两个不同的问题。一个是将它设置为新对象还是清除它是否可以,我认为Eric回答得很好。第二个问题是你是否应该忽略GC并让它工作而不试图“帮助”它 - 我会说绝对是的。让框架执行框架所做的事情,并且在必要之前不要使用它。

很多程序员都想深入挖掘,而且大多数时候它会导致更多问题而不是帮助。 GC旨在收集这些东西并为您清理它们。除非您看到一个非常具体的问题,否则您应该编写有效的代码并在收集内容时付费忽略(适当时除using关键字除外)。

答案 4 :(得分:0)

重要的观点是干净的代码。 当您创建新列表时,GC将删除旧列表(如果没有其他引用。)

答案 5 :(得分:0)

我宁愿使用List.Clear()删除所有要重复使用的元素。容量保持不变,因此不应该有额外的开销成本,让GC处理内存垃圾收集,以便您可以维护干净的代码。