C#遍历数据并且删除数据报错的原因和解决方法

一:使用foreach遍历

在项目使用foreach遍历数据并且在遍历的过程中移除数据,会报错。

集合已修改;可能无法执行枚举操作的异常

原因是在使用foreach进行遍历时,本质上调用的是IEnumerator的MoveNext方法,是每次调用next()方法,都会检查expectedModCount和 ModCount值是否相等,当我们删除元素后,ModCount会改变与expectedModCount值不同,引起报错。

**

二:使用for循环

**
使用for循环遍历:注意这种方法删除集合元素会导致索引前移导致遍历问题。

ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.

原因是在RemoveAt方法中,当移除完元素之后,数组大小发生了变更,并且会将新的元素列表重新进行位置上的对齐。

使用getRange()方法获取数据,在使用移除方法。

 try
            {
                Console.WriteLine("定时器开始计时");
                timer1.Enabled = false;
                timer1.Stop();
                if (m_list.Count >= 15)
                {
                    List<string> my_temp_list = m_list.GetRange(0, 15);
                    foreach (var item in my_temp_list)
                    {
                        m_list.Remove(item);
                    }
                    foreach (var item in my_temp_list)
                    {
                        Thread.Sleep(100);
                    }
                    Console.WriteLine("本次处理的数据是:"+string.Join(",", my_temp_list));
                    Console.WriteLine("本次剩余的数据是:" + string.Join(",", m_list));
                }
                else
                {
                    List<string> my_temp_list = m_list.GetRange(0, m_list.Count);
                    foreach (var item in my_temp_list)
                    {
                        m_list.Remove(item);
                    }
                    foreach (var item in my_temp_list)
                    {
                        Thread.Sleep(100);
                    }
                    Console.WriteLine("本次处理的数据是:" + string.Join(",", my_temp_list));
                    Console.WriteLine("本次剩余的数据是:" + string.Join(",", m_list));
                }
                if (m_list.Count>0)
                {
                    timer1.Enabled = true;
                    timer1.Start();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }

**

三:多线程操作数据:

**
使用迭代器的iterator.remove()在单线程下是不会报错的,但是在多线程情况下,一个线程修改了集合的modCount导致另外一个线程迭代时modCount与该迭代器的expectedModCount不相等,这也会报异常。

public class RemoveListForThreads implements Runnable {
    static List<String> alist = new ArrayList<>();
 
    public static void main(String[] args) {
        RemoveListForThreads s = new RemoveListForThreads();
        alist.add("a");
        alist.add("b");
        alist.add("c");
        alist.add("d");
 
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 1,
                TimeUnit.SECONDS, workQueue);
 
        for (int i = 0; i < 5; i++) {
            executor.execute(s);
        }
        executor.shutdown();
    }
 
 
    @Override
    public synchronized void run() {
        Iterator<String> iterator = alist.iterator();
            while (iterator.hasNext()) {
                String s = iterator.next();
                if (s.equals("c") && Thread.currentThread().getName().equals("pool-1-thread-1")) {
                    iterator.remove();
                    System.out.println(Thread.currentThread().getName() + " " + s);
                }
                System.out.println(Thread.currentThread().getName() + " " + s);
            }
            System.out.println(alist);
        }
}

上面这段代码创建了一个线程池,开启了五个线程,在run方法中遍历并删除“b”元素,如果该方法不加同步锁sychronized,也会抛出异常

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值