C#实现在foreach遍历中删除集合中的元素(方法总结)


在foreach中删除元素时,每一次删除都会导致集合的大小和元素索引值发生变化,从而导致在foreach中删除元素时会抛出异常。

集合已修改;可能无法执行枚举操作。
在这里插入图片描述

方法一:采用for循环,并且从尾到头遍历

  • 如果从头到尾正序遍历删除的话,有些符合删除条件的元素会成为漏网之鱼;
    正序删除举例:
   List<string> tempList = new List<string>() { "a","b","b","c" };

   for (int i = 0; i < tempList.Count; i++)
   {
       if (tempList[i] == "b")
       {
           tempList.Remove(tempList[i]);
       }
   }

   tempList.ForEach(p => {
       Console.Write(p+",");
   });

控制台输出结果:a,b,b,c
有两个2没有删除掉;
这是因为当i=1时,满足条件执行删除操作,会移除第一个b,接着第二个b会前移到第一个b的位置,即游标1对应的是第二个b。
接着遍历i=2,也就跳过第二个b。

  • 用for倒序遍历删除,从尾到头
   List<string> tempList = new List<string>() { "a","b","b","c" };

   for (int i = tempList.Count-1; i>=0; i--)
   {
       if (tempList[i] == "b")
       {
           tempList.Remove(tempList[i]);
       }
   }

   tempList.ForEach(p => {
       Console.Write(p+",");
   });

控制台输出结果:a,c,
这次删除了所有的b;

方法二:使用递归

使用递归,每次删除以后都从新foreach,就不存在这个问题了;

    static void Main(string[] args)
    {
        List<string> tempList = new List<string>() { "a","b","b","c" };
        RemoveTest(tempList);

        tempList.ForEach(p => {
            Console.Write(p+",");
        });
	}
    static void RemoveTest(List<string> list)
    {
        foreach (var item in list)
        {
            if (item == "b")
            {
                list.Remove(item);
                RemoveTest(list);
                return;
            }
        }
    }

控制台输出结果:a,c,
正确,但是每次都要封装函数,通用性不强;

方法三:通过泛型类实现IEnumerator

    static void Main(string[] args)
    {
        RemoveClass<Group> tempList = new RemoveClass<Group>();
        tempList.Add(new Group() { id = 1,name="Group1" }) ;
        tempList.Add(new Group() { id = 2, name = "Group2" });
        tempList.Add(new Group() { id = 2, name = "Group2" });
        tempList.Add(new Group() { id = 3, name = "Group3" });

        foreach (Group item in tempList)
        {
            if (item.id==2)
            {
                tempList.Remove(item);
            }
        }

        foreach (Group item in tempList)
        {
            Console.Write(item.id+",");
        }
	//控制台输出结果:1,3
    public class RemoveClass<T>
    {
        RemoveClassCollection<T> collection = new RemoveClassCollection<T>();
        public IEnumerator GetEnumerator()
        {
            return collection;
        }
        public void Remove(T t)
        {
            collection.Remove(t);
        }

        public void Add(T t)
        {
            collection.Add(t);
        }
    }
    public class RemoveClassCollection<T> : IEnumerator
    {
        List<T> list = new List<T>();
        public object current = null;
        Random rd = new Random();
        public object Current
        {
            get { return current; }
        }
        int icout = 0;
        public bool MoveNext()
        {
            if (icout >= list.Count)
            {
                return false;
            }
            else
            {
                current = list[icout];
                icout++;
                return true;
            }
        }

        public void Reset()
        {
            icout = 0;
        }

        public void Add(T t)
        {
            list.Add(t);
        }

        public void Remove(T t)
        {
            if (list.Contains(t))
            {
                if (list.IndexOf(t) <= icout)
                {
                    icout--;
                }
                list.Remove(t);
            }
        }
    }

posted @ 2019-12-16 22:01  willingtolove  阅读(10924)  评论(5编辑  收藏  举报