3

我知道有很多方法可以做得更好,但我已经在现有代码中看到了它,现在我想知道这是否会产生任何负面影响。请注意删除后的中断。因此,我一般不关心迭代器,但是,我确实关心意外行为(-> 潜在异常)。

foreach (var item in items)
{
    //do stuff
    if (item.IsSomething)
    {
        items.Remove(item); //is this safe???
        break;
    }
}

编译器是否也有可能以我不期望的方式优化某些东西?

4

4 回答 4

7

编译器生成Dispose()对在块中执行的枚举器的调用finally,但这不应该是一个问题。如果您break在删除该项目后立即,不会发生任何不好的事情,因为您不再使用枚举器。

但是,如果您想以不同的方式进行操作(出于样式原因或其他原因),则可以这样做:

var item = items.FirstOrDefault(i => i.IsSomething);
if (item != null) {
    items.Remove(item);
}

它也有点短:)(我假设您在集合中使用引用或可为空的类型)。

于 2013-02-27T08:46:12.420 回答
2

编译器和与您的应用程序相关的所有其他东西保证 SC-DRF(无数据竞争程序的顺序一致性),因此您不会看到您编写的程序和执行的程序之间的区别(即不一样)。假设items不是在多个线程之间共享,这写起来是完全安全的,并且Remove除了在循环外调用之外没有其他意外行为。

于 2013-02-27T08:45:57.963 回答
1

在 foreach 中迭代时不能更改列表。

枚举时无法修改基础集合。一种标准方法是将要删除的项目保留在第二个列表中,然后在枚举完 Items 之后,从 Items 中删除每个项目。

于 2013-02-27T08:59:42.167 回答
-1

那么你可以这样做——在处理大列表时效率更高(假设实体框架)

var reducedList = items.where(a=>a.IsSomething).toList();
foreach(var item in reducedList)
{
    reducedList.Remove(item);
}

这减少了foreach循环迭代

于 2013-02-27T08:50:07.193 回答