收集被修改;枚举操作可能无法执行

时间:2011-07-27 15:24:17

标签: c# c#-4.0 extension-methods

  

可能重复:
  Collection was modified; enumeration operation may not execute - why?

首先,我认为这不是一个重复的问题,因为此处的上下文涉及扩展方法。

我通过Extension方法将项目从一个列表移动到另一个列表时遇到此异常,我有点困惑,因为我正在删除项目的列表不是我正在迭代的列表。

例如,扩展方法至少如下所示:

public static void MoveItemsTo(this IList source, IList target, IList items)
{
    foreach (var item in items) {
        target.Add(item);
        source.Remove(item);
    }
}

这样的方法就像这样调用:

myCollectionOne.MoveItemsTo(myCollectionTwo, itemsToMove);

如果我尝试从源列表中删除项目,我只收到错误...这有点令人困惑,因为该方法正在迭代不同的列表。必须在幕后发生一些我不知道的事情......

2 个答案:

答案 0 :(得分:0)

使用常规for循环,而不是使用foreach循环。您实际上是从项目列表中删除项目,因为这是您正在迭代的内容。

for (int i = 0; i < items.Count; i++)
{
    target.Add(item);
    source.Remove(source[i]);
}

另外,你可以在for循环之后一次清除整个源列表,如果这确实是你想要完成的。

答案 1 :(得分:0)

这将返回一个新列表,该列表是项目从源移动到目标的结果,而不更改源列表。这可以通过将源列表视为不可变列表来避免问题中的拒绝问题。

void Main()
{
    var a = new List<string>() { "a","b","c" };
    var b = new List<string>() { "d" };
    var c = a.MoveItemsTo(i=>i=="b",b);
    c.Dump(); // { "d", "b" }
}

public static class Extensions
{
    public static IEnumerable<T> MoveItemsTo<T>(this IEnumerable<T> source, Func<T,bool> Predicate,IEnumerable<T> DestSource)
    {
        var newList = new List<T>(DestSource);
        newList.AddRange(source.Where(Predicate).ToList());
        return newList;
    }
}