C#集合遍历时安全增删元素的方法

七月
七月
发布时间:2026-10-14| 6人浏览过
原创

C# 集合不支持在遍历过程中直接增加或删除元素。本文将分析此限制的成因,并提供基于 LinkedList<>、List<> 和自定义链表的三种安全实现方案。

结果与背景

当处理如用户生命周期(出生与死亡)这类动态变化的集合时,需要在遍历的同时执行增删操作。由于 C# 的 foreach 机制依赖快照或迭代器状态追踪,集合结构变化会导致 InvalidOperationException。为解决此问题,以下提供三种不同数据结构的应对策略。

第一种方法:使用 LinkedList<> 锁定终点

利用双链表特性,在遍历前获取原链表的尾节点作为结束标记,并在循环末端追加新元素。注意在删除当前节点后,需提前获取下一个节点的引用,以免指针丢失。

using System;
using System.Collections.Generic;
namespace CollectionUpdateExample
{
    public class Program
    {
        // 初始化,添加0-29的整数进入链表
        private void Init(LinkedList list)
        {
            for (int i = 0; i < 30; i++)
            {
                list.AddLast(i);
            }
        }

        // 遍历并进行增删逻辑
        public void Process(LinkedList list)
        {
            // 记录遍历起始节点与原始末尾节点
            LinkedListNode nodeNow = list.First;
            LinkedListNode nodeLast = list.Last;
            LinkedListNode nodeTmp;

            // 循环直到达到原始链表的最后一个元素
            while (nodeNow != null && nodeNow != nodeLast)
            {
                // 满足被3整除条件,在链表尾部追加一个0元素
                if (nodeNow.Value % 3 == 0)
                {
                    list.AddLast(0);
                }
                
                // 满足被2整除条件,移除该元素
                if (nodeNow.Value % 2 == 0)
                {
                    // 先缓存下一个节点,再删除当前节点
                    nodeTmp = nodeNow.Next;
                    list.Remove(nodeNow);
                    // 移动指针到下一位置
                    nodeNow = nodeTmp;
                }
                else
                {
                    // 否则正常移动到下一个节点
                    nodeNow = nodeNow.Next;
                }
            }

            // 最后单独处理原始链表的尾节点
            if (nodeNow != null)
            {
                if (nodeNow.Value % 3 == 0) list.AddLast(0);
                if (nodeNow.Value % 2 == 0) list.Remove(nodeNow);
            }
        }
    }
}

第二种方法:使用 List<> 标记尾部

List<> 是基于数组的顺序表,虽然增删操作的时间复杂度较高(涉及内存移动),但仍可通过维护一个索引指针来解决遍历冲突。核心思路是记录初始容量下的尾部边界,遇到新增元素时在边界外进行;删除元素时则无需额外处理,只需保证循环范围不覆盖新增部分即可。

代码实现上需注意:因数组空间连续性,频繁增删性能较差。若集合规模较大,建议优先考虑链表方案;若需随机访问且变动较少,可尝试将符合条件的元素提取至临时列表,遍历结束后统一调用 RemoveRange 或 AddRange。

第三种方法:自定义单链表支持合并

标准的 LinkedList<> 出于防止环状结构(Loop)及保护 Last、Count 属性准确性的考虑,不支持直接将另一个链表的节点接入自身。若要高效合并两个集合,需自定义泛型链表类:

// 伪代码示意:合并两个链表的核心原理
Node current = list.Head;
while(current.Next != null) 
    current = current.Next;
current.Next = list2.Head;

此类设计允许灵活拼接节点,避免了额外的空间分配与深拷贝开销。但需自行管理遍历过程中的边界判定,以确保逻辑闭环。

完成判断与总结

验证遍历成功的方法是检查最终集合元素是否符合既定的数值规则(如模运算过滤后的剩余值及追加值的数量)。上述方法规避了修改正在迭代的集合带来的系统崩溃。以上就是C#集合遍历时增删元素方法的详细内容,更多关于C#数据处理技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。