在这个foreach循环中是否创建了垃圾?

时间:2011-06-10 01:44:47

标签: c# list garbage-collection foreach memory-management

我遇到了一种方法来改变foreach循环中的列表,方法是转换为自己的列表,如下所示:

foreach (var item in myList.ToList())
{
     //add or remove items from myList
}

(如果您尝试直接修改myList,则抛出错误,因为枚举器基本上将其锁定)

这是有效的,因为它不是被修改的原始myList。我的问题是,当循环结束时(即从garbage方法返回的List,此方法是否会创建ToList?对于小循环,是否最好使用{ {1}}以避免产生垃圾?

5 个答案:

答案 0 :(得分:5)

第二个列表将是垃圾,在构建第二个列表中使用的枚举器将有垃圾,并在枚举器中添加foreach将产生的,无论是否有第二个列表,你都可以拥有它。

您应该切换到for吗?也许, if 你可以指出这个代码区域是一个真正的性能瓶颈。否则,代码是为了简化和可维护性。

答案 1 :(得分:3)

是。 ToList()会创建另一个需要进行垃圾回收的列表。

答案 2 :(得分:1)

这是一项有趣的技术,我将在未来牢记这一点! (我不敢相信我从未想过那个!)

无论如何,是的,你正在构建的列表并没有神奇地取消分配。这种技术可能存在的性能问题是:

  1. 增加内存使用量(构建List,与IEnumerable分开)。可能没什么大不了的,除非你频繁地这样做,或者IEnumerable非常大。
  2. 降低速度,因为它必须立即通过IEnumerable来构建List
  3. 此外,如果枚举IEnumerable有副作用,则会全部由此过程触发。
  4. 除非这实际上在内部循环中,或者您正在使用非常大的数据集,否则您可以毫无问题地执行此操作。

答案 3 :(得分:1)

是的,ToList()方法会创建“垃圾”。我只是索引。

for (int i = MyList.Count - 1; 0 <= i; --i)
{
    var item = MyList[i];
    //add or remove items from myList
}

答案 4 :(得分:0)

它是非确定性的。但是,从调用ToList()创建的引用最终将是GCd。

我不会太担心它,因为它最多只能包含引用或小值类型。