【问题标题】:Is garbage created in this foreach loop?在这个 foreach 循环中是否创建了垃圾?
【发布时间】:2011-09-12 04:04:43
【问题描述】:

我遇到了一种方法来更改 foreach 循环中的列表,方法是像这样转换为本身的列表:

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

(如果您尝试直接修改myList,则会引发错误,因为枚举器基本上锁定了它)

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

【问题讨论】:

  • 推理不是倒退吗,至少给出注释“//从myList中添加或删除项目”?它不应该读成(长):“这行得通,因为它不是myList 迭代(而是使用ToList() 创建的副本),所以myList 可以在foreach 循环。”

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这是不确定的。但是调用ToList()创建的引用最终会被GCd。

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

    【讨论】:

      【解决方案3】:

      这是一项有趣的技术,我会牢记在心! (我不敢相信我从来没有想过这个!)

      无论如何,是的,您正在构建的列表不会神奇地自行取消分配。这种技术可能存在的性能问题是:

      1. 内存使用增加(构建List,与IEnumerable 分开)。可能没什么大不了的,除非您经常这样做,或者IEnumerable 非常大。
      2. 速度降低,因为它必须立即通过IEnumerable 才能构建List
      3. 另外,如果枚举IEnumerable有副作用,都会被这个进程触发。

      除非这实际上是在一个内部循环中,或者您正在处理非常大的数据集,否则您可以毫无问题地执行此操作。

      【讨论】:

        【解决方案4】:

        第二个列表将是垃圾,将有一个用于构建第二个列表的枚举器的垃圾,并添加foreach将产生的枚举器,你无论有没有第二个列表,都会有。

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

        【讨论】:

          【解决方案5】:

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

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

          【讨论】:

          • 我会推迟进行这种优化,直到原始代码被证明是一个瓶颈。如果不是,那么降低代码的可读性是没有意义的。
          猜你喜欢
          • 2014-10-30
          • 1970-01-01
          • 2014-10-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-04-08
          • 1970-01-01
          • 2011-07-16
          相关资源
          最近更新 更多