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);
            }
        }
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM