Best practice to avoid InvalidOperationException: Collection was modified?

前端 未结 4 904
没有蜡笔的小新
没有蜡笔的小新 2021-02-08 00:42

Very often I need something like that:

 foreach (Line line in lines)
 {
    if (line.FullfilsCertainConditions())
    {
       lines.Remove(line)
    }
 }


        
相关标签:
4条回答
  • 2021-02-08 00:44

    You could simply replace original list with filtered one:

    lines = lines.Where(line => line.FullfilsCertainConditions()).ToList();
    
    0 讨论(0)
  • 2021-02-08 00:52

    This is baked directly into List<T>:

    lines.RemoveAll(line => line.FullfilsCertainConditions());
    

    or in C# 2.0:

    lines.RemoveAll(delegate(Line line) {
        return line.FullfilsCertainConditions();
    });
    

    In the non-List<T> case (your edit to the question), you could wrap this something like below (untested):

    static class CollectionUtils
    {
        public static void RemoveAll<T>(IList<T> list, Predicate<T> predicate)
        {
            int count = list.Count;
            while (count-- > 0)
            {
                if (predicate(list[count])) list.RemoveAt(count);
            }
        }
        public static void RemoveAll(IList list, Predicate<object> predicate)
        {
            int count = list.Count;
            while (count-- > 0)
            {
                if (predicate(list[count])) list.RemoveAt(count);
            }
        }
    }
    

    Since UIElementCollection implements the (non-generic) IList this should work. And quite conveniently, with C# 3.0 you can add a this before IList / IList<T> and have it as an extension method. The only subtlety is that the parameter to the anon-method will be object, so you'll need to cast it away.

    0 讨论(0)
  • 2021-02-08 00:57

    Also you can just use while loop.

    int i = 0;
    while(i < lines.Count)
    {
      if (lines[i].FullfilsCertainConditions())
      {
         lines.RemoveAt(i);
      }
      else {i++;}
    }
    
    0 讨论(0)
  • 2021-02-08 01:08

    Build a new list instaed:

    public IList<Line> GetListWithoutFullfilsCertainConditions(IList<Line> fullList) 
    {
        IList<Line> resultList = new List<Line>(fullList.Count);
    
        foreach (Line line in fullList)
        {
           if (!line.FullfilsCertainConditions())
           {
              resultList.Add(line)
           }
        }
    
        return resultList;
    }
    
    0 讨论(0)
提交回复
热议问题