C#中动态移除LinkedList数组元素时遇索引越界异常问题
解决C# LinkedList动态移除元素时的索引越界问题
嘿,我来帮你拆解下这个问题!你遇到的索引越界异常,核心是对LinkedList的特性理解有偏差,再加上临时链表的初始化逻辑出错,才导致了这些问题。
先说说你代码里的两个关键问题
1. 临时链表的复制逻辑错误
看你第一个循环里的代码:每次k循环时,只要原链表元素不为null,就重新new一个listOfSmtObjectsTemp[j],再添加当前元素。这会导致每次符合条件的元素都会覆盖之前创建的临时链表,最后listOfSmtObjectsTemp[j]里只会保留最后一个符合条件的元素,完全不是原链表的完整副本。后面访问SMTobjTemp.ElementAt(item)时,索引自然会超出临时链表的实际长度,触发越界异常。
2. 用索引操作LinkedList是大忌
LinkedList是双向链表结构,它没有内置的索引器,ElementAt(index)方法是通过从头节点开始遍历index次来找到元素的——不仅效率极低,而且当你移除临时链表的元素后,链表的长度会变化,原来的索引和元素的对应关系直接被破坏,继续用旧索引遍历肯定会踩坑。
正确的实现方式
第一步:正确复制原链表到临时链表
先初始化每个临时链表,再批量添加原链表的非null元素:
// 先初始化所有临时链表 LinkedList<SMTObjects>[] listOfSmtObjectsTemp = new LinkedList<SMTObjects>[MAX_LEVEL]; for (int j = 0; j < MAX_LEVEL; j++) { listOfSmtObjectsTemp[j] = new LinkedList<SMTObjects>(); // 遍历原链表,添加所有非null元素到临时链表 foreach (var obj in listOfSmtObjects[j]) { if (obj != null) { listOfSmtObjectsTemp[j].AddLast(obj); } } }
第二步:正确移除链表元素(两种高效方式)
LinkedList的正确操作姿势是用节点遍历,或者先收集要移除的元素再批量处理,绝对不要用索引:
方式一:先收集要移除的元素,再批量移除
适合需要复杂条件判断的场景,避免遍历过程中修改链表结构:
for (int index = 0; index < MAX_LEVEL; index++) { var smtObj = listOfSmtObjects[index]; var smtObjTemp = listOfSmtObjectsTemp[index]; if (smtObj == null || smtObjTemp == null) continue; // 先收集所有符合移除条件的元素 var itemsToRemove = new List<SMTObjects>(); foreach (var tempObj in smtObjTemp) { // 这里替换成你的实际判断条件 if (smtObj.Contains(tempObj)) { itemsToRemove.Add(tempObj); } } // 批量移除元素 foreach (var item in itemsToRemove) { smtObjTemp.Remove(item); } }
方式二:用LinkedListNode遍历,直接移除节点(效率更高)
适合简单条件的移除,提前保存下一个节点,避免遍历中断:
for (int index = 0; index < MAX_LEVEL; index++) { var smtObj = listOfSmtObjects[index]; var smtObjTemp = listOfSmtObjectsTemp[index]; if (smtObj == null || smtObjTemp == null) continue; var currentNode = smtObjTemp.First; while (currentNode != null) { // 必须先保存下一个节点,否则移除当前节点后currentNode会失效 var nextNode = currentNode.Next; // 这里替换成你的实际判断条件 if (smtObj.Contains(currentNode.Value)) { smtObjTemp.Remove(currentNode); } currentNode = nextNode; } }
额外提醒:如果是要修改原链表
如果你本来的需求是从原LinkedList中移除元素,同样不要用索引,直接用节点遍历的方式:
foreach (var list in listOfSmtObjects) { if (list == null) continue; var currentNode = list.First; while (currentNode != null) { var nextNode = currentNode.Next; // 你的判断条件,比如移除非null元素 if (currentNode.Value != null) { list.Remove(currentNode); } currentNode = nextNode; } }
内容的提问来源于stack exchange,提问作者usmanharoon
相关产品推荐
相关产品推荐

