Add()是向List添加元素的唯一推荐方法,预估容量可避免多次数组复制;AddRange()适合批量添加但需判空;Insert()不应替代Add();集合初始化器仅限构造时使用。

用 Add() 最直接,但别在循环里反复调用
向 List<t></t> 添加单个元素,Add() 是唯一该用的方法。它时间复杂度是均摊 O(1),底层自动扩容,但每次扩容要复制数组——如果提前知道大概数量,用带容量的构造函数能省掉多次复制。
- 正确:创建时预估大小:
var list = new List<string>(100);</string> - 错误:边加边扩,尤其在 for 循环里反复
Add()且没预设容量,可能触发 5–10 次数组复制 - 注意:
Add()不返回新列表,也不支持链式调用;它就地修改原对象
AddRange() 适合批量添加,但传 null 会直接抛 ArgumentNullException
一次性加多个元素,比如另一个集合、数组或 LINQ 查询结果,AddRange() 比循环调用 Add() 快且语义清晰。但它对参数零容忍——哪怕传个 null,立刻崩。
- 安全写法:
if (items != null) list.AddRange(items); - 常见坑:把 LINQ 方法(如
Where())结果直接传进去,却忘了它可能返回null(极少,但自定义迭代器可能) - 性能提示:如果
items是IEnumerable<t></t>且不是ICollection<t></t>,AddRange()会先遍历一次计数再分配空间,不如手动转成数组或用foreach
别误用 Insert() 当 Add() 用
Insert(index, item) 是往指定位置塞元素,不是“加到末尾”的替代品。它内部要移动 index 后所有元素,复杂度 O(n)。新手常把它和 Add() 混淆,以为 Insert(list.Count, x) 更“通用”——其实纯属多此一举,还慢。
- 加到最后?只用
Add(),干净又快 - 真要插中间?确认业务逻辑确实需要顺序敏感,否则考虑用
Dictionary或重构数据结构 - 错误示例:
list.Insert(list.Count, "hello");—— 这行代码等于list.Add("hello");,但多了一次索引检查+位移开销
初始化阶段用集合初始化器更简洁,但仅限构造时
C# 支持集合初始化语法:new List<int> { 1, 2, 3 }</int>。它本质是调用 Add(),但写起来少敲几行,也避免了空构造 + 多次调用的啰嗦。不过这玩意儿只能在对象创建那一刻用,之后不能这么写。
- 合法:
var nums = new List<int> { 10, 20, 30 };</int> - 非法:
nums = { 40, 50 };(编译不过) - 注意:初始化器里的每个值都会触发一次
Add(),所以如果元素很多,仍建议预设容量:new List<string>(1000) { "a", "b", ... }</string>
实际写的时候,最常被忽略的是容量预估——不是所有 List 都要设,但读配置、解析固定格式文件、接收已知长度 API 响应时,漏掉这一句,性能损耗就在那儿,不报错,只变慢。


















