ImmutableList 是自带结构共享、线程安全、值语义明确的不可变集合类型,非只读包装;必须通过静态工厂方法创建,修改操作返回新实例,批量变更应使用 Builder 模式,随机访问为 O(log n)。

ImmutableList 不是“只读包装”,也不是“禁止修改的 List 它没有公共构造函数,也不能用 错误写法: 调用 常见误判现象: 需要循环添加/删除几十次以上时,直接链式调用效率低,应先获取 注意: 两者语义完全不同: 最容易被忽略的一点:List 做只读场景,大概率踩坑;但用对了模式,它比 ReadOnlyCollection 更可靠、比反复拷贝 List 更省内存。
创建 ImmutableList
new ImmutableList。所有实例必须通过 ImmutableList.Create()、ImmutableList.Empty 或从其他集合转换而来:
var list = ImmutableList.Create(1, 2, 3); —— 最常用,适合已知元素的初始化var empty = ImmutableList —— 比 Create() 更轻量,无装箱开销var fromArray = ImmutableArray.Create(1, 2, 3).ToImmutableList(); —— 适合从紧凑数组转树形结构var fromEnumerable = source.ToImmutableList(); —— 注意:这是 LINQ 扩展方法,需引用 System.Linq,且会遍历整个源序列new List —— 多此一举,还引入了不必要的中间对象。修改操作永远返回新实例,原对象不变
Add()、Remove()、SetItem() 等方法,不会改变当前实例,而是返回逻辑上“修改后”的新 ImmutableList:
var newList = oldList.Add(4); —— oldList 仍为 [1,2,3],newList 是 [1,2,3,4]list.Add(4).Remove(1).Insert(0, 99),但每次调用都生成一个新实例Add() 会创建 100 个中间树节点,实际只保留最终结果list.Add(x); 看似执行了,但没接返回值 → 实际什么都没发生,原变量仍指向旧实例。批量增删请务必用 Builder 模式
Builder,累积变更后再一次性冻结:
var builder = list.ToBuilder(); —— 开销极小,底层是可变数组builder.Add(x); builder.RemoveAt(i); builder[0] = y; —— 支持全部可变操作var final = builder.ToImmutable(); —— 此刻才真正构建不可变结构,仅一次分配ImmutableList.CreateBuilder 预分配,避免 builder 内部扩容builder.ToImmutable() 返回的是新 ImmutableList,builder 本身仍可继续用(但通常不建议)。别把 ImmutableList
ReadOnlyCollection 只是 List 的只读门面,底层集合仍可被其他引用修改ImmutableList 一旦创建,内存中再无任何路径能修改其内容,包括反射(除非用 Unsafe)List 引用,用 ReadOnlyCollection 更轻;但若需跨线程共享或保证绝对不变性,必须选 ImmutableList
IReadOnlyList 接口只是契约,不能保证实现类是否真不可变 —— ImmutableList 实现了它,但 List 也实现了ImmutableList 底层是平衡树,随机索引访问是 O(log n),不是 O(1)。高频随机读场景(如配置项查表),优先考虑 ImmutableArray 或 ReadOnlyMemory 视图。










