2012-07-30 78 views
6

我有一个可变的类,里面有一个私人的List<T>字段。在我的班级的Reset()方法中,我应该使用其Clear()方法清除列表,还是只将其字段分配给一个新列表?请注意,列表不是公开的,只能由类本身使用。所以分配一个新的列表应该使旧的无法访问。由于Clear()方法is an O(n) operation,我想知道只是分配一个新列表的缺点是什么。清除私人收藏或将其设置为空?

回答

5

我能想到的唯一缺点是如果你需要再次使用列表,你将不得不为它分配新的空间。

对它进行清零只会使列表及其内容(假设没有其他引用)符合GC要求。清除它将删除项目,但保留分配的内存。

就我个人而言,即使我再次需要它,尺寸也会完全改变。

更新:根据下面的注释,您声明这些对象将在一个对象池中进行管理。我会建议创建一个小型分析控制台应用程序来获得最终答案。现在讨论的内容正在进入你的实现细节和对象池的预期用法,这可以很容易地改变答案。

一般来说,如果你的列表长度没有太大变化,并且总是需要,我会使用Clear来避免为列表分配新的内存。如果列表长度容易发生很大变化,或者使用有时很稀疏 - 我会倾向于将它归零,以便回收内存并通过列表的懒惰实例获得一些次要好处。

+0

因此,如果我有一个2k字节的字节列表,哪个会更快?我,调用Clear或GC,做重新分配?我问这个是因为我内部有大约1-2k个带有这些列表的对象,所以我想确定哪个更好,性能更好。 – 2012-07-30 08:10:13

+0

@ d4wn我个人不会担心表现,除非你能证明这是一个问题。这取决于你想要对列表做什么。如果这些项目不再需要,但是您可能需要列表大小或者希望避免为列表增长重新分配内存,我会“清除”。如果你以后不关心这个列表,或者它可能会缩小很多,我会'list = null; list = new List ()'。在任何一种情况下,GC都会收集许多对象,因此无关紧要。任何潜在的性能差异将是O(n)迭代与列表增长重新分配之间的差异。 – 2012-07-30 08:16:35

+0

所以,还有一个问题:为什么我要“避免为列表增长重新分配内存”?我为这些对象使用了一个池,只要应用程序正在运行,它们会一遍又一遍地重复使用。每次做重新分配听起来都很昂贵,但我不太了解GC以及这个过程对性能的影响。 – 2012-07-30 08:23:24

0

那么为什么是空的呢?这将这样的伎俩给你,让堆上垃圾收集旧列表逗留,而访问列表中的现有方法可以继续到一个新的空列表功能:

this.FooList = new List<Foo>(); 
+1

我写过“为其字段分配新列表”。我使用“取消”这个词的原因是因为它使得字段无法访问并且允许GC收集它。但是你是对的,我应该编辑这个问题。无论如何,问题是哪个更快,他们对另一个有什么优势/劣势。 – 2012-07-30 08:03:37

+0

将其删除或重新赋值与GC眼中的相同。如果你将它清空并稍后重新分配,你会得到懒惰实例的温和益处。 – 2012-07-30 08:06:25

0

Reset呼叫我后会在构造函数被调用后使对象保持与它处于同一状态。

如果你的构造函数创建了一个新的空List然后这样做。如果不能使它变成null

+0

这就是我想要决定的。在构造函数中一次性地设置列表,并通过清除它来反复使用它,或者在需要时懒惰地创建列表,并在Reset中将其设置为null(或新列表)。 – 2012-07-30 08:12:35

+0

@ d4wn在我看来,我认为绩效不应该推动这个决定。我认为使它成为'null'并且延迟加载是最干净的,我会这样做。 – ForkandBeard 2012-07-30 08:21:21