3

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

例如:

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

myList = new List<element>();

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

4

6 回答 6

6

myList.Clear()比编码更容易myList = new List<element>();

msdn: List.Clear 方法

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

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

于 2012-07-18T18:54:22.783 回答
6

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

如果列表很小,最好只创建一个新列表,或者调用Clear(). 如有疑问,请测量性能。

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

  1. 一般来说,如果你不重用对象,代码会更干净,更容易推理。垃圾回收的成本低,混淆代码的成本高。
  2. 考虑一下如果转储列表内容的代码在另一个函数中会发生什么,因为它很可能是。一旦您将该列表从其本地上下文中传递出去,就可能存在对同一列表的非本地引用。其他代码可能正在修改列表,或者可能(错误地)假设您没有修改它。
于 2012-07-18T18:58:17.577 回答
1

听起来你在问两个不同的问题。一个是是否可以将其设置为新对象或只是清除它,我认为 Eric 回答得很好。第二个是你是否应该忽略 GC 并让它工作而不试图“帮助”它 - 对此,我会说绝对是的。让框架做框架做的事,直到你不得不这样做。

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

于 2012-07-18T19:16:12.533 回答
1

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

于 2012-07-18T18:55:45.983 回答
0

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

于 2012-07-18T19:04:16.703 回答
0

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

于 2012-07-18T19:00:05.393 回答