【问题标题】:Foreach loop does not advance nor throw an exceptionForeach 循环不前进也不抛出异常
【发布时间】:2016-05-28 09:34:27
【问题描述】:

为了简单起见;想象一个循环的类车;其中每辆车都包含一个汽车系统列表;第二个循环遍历每个系统,将它们从那辆汽车上移除。理想情况下,最后每辆车都没有系统。

这是简化的代码。

public class ParseCars: MonoBehaviour 
{
    foreach (cars a_car in cars_list)
    {
        // retrieve the systems for the current car
        List<car_system> systems_list = a_car.ReturnSystemList();

        foreach (car_system a_system in systems_list)
        {
            a_car.RemoveSystem(a_system);
        }
        Debug.Log("removed all systems for this car);
    }
}

删除系统时,我所做的只是调用汽车类中包含的列表的 Remove 方法。

第一次移除成功;然后当需要删除下一个元素时,它不会再次执行 remove 调用,而是返回上一个 foreach,加载列表中的下一辆车。

查看下一个系统的名称;我仍然看到前一个,就像循环不会获取列表中的下一个项目一样。 我没有看到任何异常,这是我第一次看到这种行为,并且无法真正弄清楚发生了什么,因为我没有从调试器中得到任何反馈。

【问题讨论】:

  • 显然这不是您算法的精确伪代码。正如@Saeid Yazdani 建议的那样,您可能会修改您的收藏(尽管您应该得到一个错误)或做其他错误。如果您切换到为您不会得到“CollecionModifiedException”,但如果不修改索引,代码将无法工作。我建议您使用 List.RemoveAll 方法清空列表或创建一个临时列表,其中包含要删除的元素并在原始列表上使用 RemoveRange
  • 简化了;否则我应该添加至少 3 个以上的类和方法。 Saeid 发现了这个问题。
  • 嘿@newbiez 怎么了。不要忘记在编程中作为一般主体,您在删除时经常需要遍历列表 BACKWARDS。赛义德在这里给了你答案。但不要忘记那个“技巧”,它是软件的基础。
  • 嘿@JoeBlow;我懂了。我认为删除的方向无关紧要,因为 C# 列表不是像链表那样的顺序列表,也不是堆栈或堆。为何即使在这种情况下,这个老“伎俩”仍然存在?
  • @nbew - 我不知道 :O 我只是提醒一下,有时你必须使用那个“技巧”!

标签: c# loops unity3d foreach


【解决方案1】:

您应该使用for 循环。在foreach 中,您不能更改循环下的集合。

AFAIK,foreach 使用枚举器,foreach 中的迭代变量是只读的。枚举器返回对象的副本......这就是为什么你没有得到异常。您实际上是编辑了对象的副本而不是对象本身。

【讨论】:

  • 这就是为什么我看不到错误,谢谢!!!!那么为什么VS在尝试修改不可修改的对象时不抛出异常呢?
  • AFAIK,foreach 使用枚举器,foreach 中的迭代变量是只读的。枚举器返回对象的副本......这就是为什么你没有得到异常。您实际上是编辑了对象的副本而不是对象本身。
  • 有道理;从逻辑上讲,操作是合法的,所以编译器很高兴。谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-03-17
  • 2016-04-03
  • 1970-01-01
  • 2020-06-22
  • 2010-10-02
  • 2023-03-24
  • 2018-06-28
  • 1970-01-01
相关资源
最近更新 更多