我正在寻找一种更好的模式,用于处理每个元素的列表,然后根据结果从列表中删除。

你不能在foreach (var element in X)中使用.Remove(element)(因为它会导致Collection被修改;枚举操作可能无法执行。例外)……你也不能使用for (int I = 0;i < elements.Count();i++)和. removeat (i),因为它破坏了你在集合中相对于i的当前位置。

有没有一种优雅的方式来做到这一点?


当前回答

使用属性跟踪要删除的元素,并在处理后将它们全部删除。

using System.Linq;

List<MyProperty> _Group = new List<MyProperty>();
// ... add elements

bool cond = false;
foreach (MyProperty currObj in _Group)
{
    // here it is supposed that you decide the "remove conditions"...
    cond = true; // set true or false...
    if (cond) 
    {
        // SET - element can be deleted
        currObj.REMOVE_ME = true;
    }
}
// RESET
_Group.RemoveAll(r => r.REMOVE_ME);

其他回答

只是想添加我的2美分,以防这有助于任何人,我有一个类似的问题,但需要从一个数组列表中删除多个元素,而它正在被迭代。最高的upvotes的答案在很大程度上为我做了,直到我遇到错误,意识到在某些情况下,索引大于数组列表的大小,因为多个元素被删除,但循环的索引没有跟踪它。我用一个简单的检查解决了这个问题:

ArrayList place_holder = new ArrayList();
place_holder.Add("1");
place_holder.Add("2");
place_holder.Add("3");
place_holder.Add("4");

for(int i = place_holder.Count-1; i>= 0; i--){
    if(i>= place_holder.Count){
        i = place_holder.Count-1; 
    }

// some method that removes multiple elements here
}

使用.ToList()将创建一个列表的副本,正如这个问题中所解释的: ToList()—它是否创建一个新列表?

通过使用ToList(),可以从原始列表中删除,因为实际上是在迭代一个副本。

foreach (var item in listTracked.ToList()) {    

        if (DetermineIfRequiresRemoval(item)) {
            listTracked.Remove(item)
        }

     }

使用属性跟踪要删除的元素,并在处理后将它们全部删除。

using System.Linq;

List<MyProperty> _Group = new List<MyProperty>();
// ... add elements

bool cond = false;
foreach (MyProperty currObj in _Group)
{
    // here it is supposed that you decide the "remove conditions"...
    cond = true; // set true or false...
    if (cond) 
    {
        // SET - element can be deleted
        currObj.REMOVE_ME = true;
    }
}
// RESET
_Group.RemoveAll(r => r.REMOVE_ME);

我将从一个过滤掉您不想保留的元素的LINQ查询中重新分配列表。

list = list.Where(item => ...).ToList();

除非列表非常大,否则这样做应该不会有明显的性能问题。

一个简单而直接的解决方案:

在你的集合上使用一个标准的for循环,并使用RemoveAt(i)来删除元素。