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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • C#使用foreach语句遍历队列(Queue)的方法

    本文实例讲述了C#使用foreach语句遍历队列(Queue)的方法.分享给大家供大家参考.具体如下: using System; using System.Collections; public class QueuesW3 { static void Main(string[] args) { Queue a = new Queue(10); int x = 0; a.Enqueue(x); x++; a.Enqueue(x); foreach (int y in a) { Console.

  • C#使用foreach语句简单遍历数组的方法

    本文实例讲述了C#使用foreach语句简单遍历数组的方法.分享给大家供大家参考.具体如下: using System; public class jb51demo { public static void Main() { int sum = 0; int[] nums = new int[10]; // give nums some values for(int i = 0; i < 10; i++) nums[i] = i; // use foreach to display and su

  • C#使用foreach循环遍历数组完整实例

    本文实例讲述了C#使用foreach循环遍历数组的方法.分享给大家供大家参考,具体如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //声明数组. 第一种方法. 声明并分配元素大小. int[] Myint

  • C#使用foreach语句遍历二维数组的方法

    本文实例讲述了C#使用foreach语句遍历二维数组的方法.分享给大家供大家参考.具体分析如下: 如果通过for语句循环遍历二维数组需要两重循环才可以,二foreach语句只需要一次可以完全遍历整个二维数组,下面是代码演示 using System; public class w3demo{ public static void Main() { int sum = 0; int[,] nums = new int[3,5]; // give nums some values for(int i

  • C#使用foreach遍历哈希表(hashtable)的方法

    本文实例讲述了C#使用foreach遍历哈希表(hashtable)的方法.分享给大家供大家参考.具体实现方法如下: using System; using System.Collection; namespace HashSampleApplication1 { class Program { static void Main() { Hashtable hash = new Hashtable(); hashtable[1] = "kaka"; hashtable[2] = &qu

  • C#中foreach语句使用break暂停遍历的方法

    本文实例讲述了C#中foreach语句使用break暂停遍历的方法.分享给大家供大家参考.具体分析如下: 下面的代码演示了在C#中使用foreach时如何通过break语句暂停数据遍历 using System; public class w3demo { public static void Main() { int sum = 0; int[] nums = new int[10]; // give nums some values for(int i = 0; i < 10; i++) n

  • C#使用foreach语句遍历堆栈(Stack)的方法

    本文实例讲述了C#使用foreach语句遍历堆栈(Stack)的方法.分享给大家供大家参考.具体如下: using System; using System.Collections; public class StacksW3 { static void Main(string[] args) { Stack a = new Stack(10); int x = 0; a.Push(x); x++; a.Push(x); foreach (int y in a) { Console.WriteL

  • C#中用foreach语句遍历数组及将数组作为参数的用法

    对数组使用 foreach C#提供 foreach 语句. 该语句提供一种简单.明了的方法来循环访问数组或任何可枚举集合的元素. foreach 语句按数组或集合类型的枚举器返回的顺序处理元素,该顺序通常是从第 0 个元素到最后一个元素. 例如,以下代码创建一个名为 numbers 的数组,并使用 foreach 语句循环访问该数组: int[] numbers = { 4, 5, 6, 1, 2, 3, -2, -1, 0 }; foreach (int i in numbers) { Sy

  • C#使用yield关键字让自定义集合实现foreach遍历的方法

    foreach遍历是C#常见的功能,而本文通过实例形式展现了C#使用yield关键字让自定义集合实现foreach遍历的方法.具体步骤如下: 一般来说当我们创建自定义集合的时候为了让其能支持foreach遍历,就只能让其实现IEnumerable接口(可能还要实现IEnumerator接口) 但是我们也可以通过使用yield关键字构建的迭代器方法来实现foreach的遍历,且自定义的集合不用实现IEnumerable接口 注意:虽然不用实现IEnumerable接口 ,但是迭代器的方法必须命名为

  • C#使用foreach语句遍历集合类型的方法

    本文实例讲述了C#使用foreach语句遍历集合类型的方法.分享给大家供大家参考.具体如下: 这里演示如何实现可与 foreach 语句一起使用的集合类 using System; using System.Collections; public class Tokens: IEnumerable { private string[] elements; Tokens(string source, char[] delimiters) { elements = source.Split(deli

随机推荐