You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 14:17:50