Remove()按值删第一个匹配项,值不存在则无操作;RemoveAt()按索引删除,越界抛ArgumentOutOfRangeException;误用Remove()无法批量删同值元素。
用
和
删除单个元素时要注意什么
这两个方法最常用,但行为完全不同:
按值匹配第一个相等元素并删除,
按索引删除。如果值不存在,
什么也不做且不报错;而
索引越界会直接抛
。
常见错误是误用
试图删多个同值元素——它只删第一个。比如
遇到
后变成
,不是预期的
。
实操建议:
确认要删的是“某个值”还是“第几个位置”,再选方法
用
前务必检查
若需删所有匹配项,别用循环调
(可能跳过元素),改用
批量删除必须用
,别手写 for 循环
在遍历
时用
或
调
,极易因索引偏移漏删或越界。正确做法是把筛选逻辑交给
,它内部一次性处理,安全高效。
示例:删掉所有偶数
注意点:
谓词函数返回
的元素会被删除
返回值是实际删除的元素个数,可用于校验
不能在谓词里修改
本身(比如再调
),会抛
对引用类型,判断依据是对象引用或重载的
,不是简单地址比较
按条件删又想保留原顺序?
不行,得用
有人想“找出要删的,再逐个删”,于是写
——这会出错,因为
修改了原集合,导致
迭代器失效。
更糟的是,即使不报错,结果也不可靠:重复值、顺序错乱、部分漏删。
正确思路是“构造新集合”而非“边查边删”:
C知道
CSDN推出的一款AI技术问答工具
下载
或者用
(推荐):
二者区别:
原地操作,内存友好,适合大列表
创建新列表,原
引用改变,适合需要保留旧引用场景(如被其他变量持有)
LINQ 方式可链式组合(如加
),
只能单条件
删除后立即访问
或索引要小心线程安全
本身不是线程安全的。如果多个线程同时调
或混合读写,
可能不准,甚至抛
(“集合已修改”)。
没有锁的情况下,以下代码危险:
因为
检查和
访问之间可能已被其他线程删空。
解决方式:
单线程场景无需担心
多线程下要么加
,要么改用
/
等线程安全集合(但它们不支持随机索引)
若只是读多写少,可用
快照一次再操作:
真正容易被忽略的是:删除操作看似简单,但一旦混入循环、多线程或引用共享,行为就依赖执行时机和集合状态。动手前先明确——你要删的是“值”还是“位置”,是否允许多删,有没有并发,以及谁还在用这个
引用。
Remove()RemoveAt()Remove()RemoveAt()Remove()RemoveAt()ArgumentOutOfRangeExceptionRemove()list.Remove(5)[5, 5, 1][5, 1][1]RemoveAt()index >= 0 && index Remove()RemoveAll()RemoveAll()ListforforeachRemove()RemoveAll()list.RemoveAll(x => x % 2 == 0);truelistRemoveAllInvalidOperationExceptionEquals()FindAll().ForEach()Where().ToList()list.FindAll(x => x > 10).ForEach(list.Remove)Remove()ForEachlist = list.Where(x => x <= 10).ToList();RemoveAll()list.RemoveAll(x => x > 10);RemoveAll()Where().ToList()listOrderBy()RemoveAll()CountListRemoveAll()CountInvalidOperationExceptionif (list.Count > 0) { var first = list[0]; }Count[0]lockConcurrentBagConcurrentQueueToArray()var snapshot = list.ToArray();list