【问题标题】:for loop ends prematurely when objects are removed删除对象时 for 循环提前结束
【发布时间】:2023-03-22 02:35:02
【问题描述】:

您好,我遇到了 for 循环的问题。

看起来像这样

for (int i = 0; i < ObjectManager.Instance.Objects.Count; i++)
{
   if (ObjectManager.Instance.Objects[i] is Asteroid)
   {
      ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
   }
}

但是当我删除对象时计数会变短,这会导致循环过早结束。有没有办法在没有一堆额外循环的情况下做到这一点。

【问题讨论】:

  • 倒序计数怎么样。
  • ObjectManager.Instance.Objects的类型是什么?
  • 你可以向后循环

标签: c# list for-loop


【解决方案1】:

你为什么不循环向后

// Just change the order from Count - 1 down to 0 
for (int i = ObjectManager.Instance.Objects.Count - 1; i >= 0; --i)
{
   if (ObjectManager.Instance.Objects[i] is Asteroid)
   {
      ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
   }
}

如果你必须循环forward(例如,如果实例应该按照它们创建的顺序被删除,因为它们是相互依赖的)你可以修改for循环这样:

for (int i = 0; i < ObjectManager.Instance.Objects.Count;)  // <- No increment here
  if (ObjectManager.Instance.Objects[i] is Asteroid)
    ObjectManager.Instance.Objects.Remove(ObjectManager.Instance.Objects[i]);
  else 
    i += 1; // <- Increment should be here!

还有一种可能是Linq

ObjectManager.Instance.Objects.RemoveAll(item => item is Asteroid);

【讨论】:

    【解决方案2】:

    三个选项:

    • 如果ObjectManager.Instance.ObjectsList&lt;T&gt;,请将List&lt;T&gt;.RemoveAll 与谓词一起使用,从而使您的代码更加更简单:

      // This replaces your whole loop...
      ObjectManager.Instance.Objects.RemoveAll(x => x is Asteroid);
      
    • 从集合的结束开始计数,而不是从开始计数,这样以后就不需要调整索引了:

      for (int i = ObjectManager.Instance.Objects.Count - 1; i >= 0; i--)
      
    • 只需在调用Remove 后递减i,以便在下一次迭代中查看正确的索引。

    请注意,在第二个和第三个选项中,如果在使用 4 次之前将表达式 ObjectManager.Instance.Objects 提取到局部变量中,您的代码将更易于阅读。还可以考虑使用RemoveAt(i) 而不是Remove(instances[i]),假设RemoveAt 可用于您正在使用的类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多