.NET 8 中不存在 FrozenDictionary 类型,所谓“冻结集合”实为 ImmutableArray 配合手动优化实现的只读集合;替代方案包括预排序 ImmutableArray + BinarySearch 或静态只读数组 + ReadOnlySpan。

FrozenDictionary 类型——这是个常见误传。官方文档、源码和 NuGet 包(System.Collections.Immutable v8.0.0)里都不存在这个类型。所谓“冻结集合”在 .NET 8 中实际指 **构建完成后不可修改 + 底层内存布局固定 + 零写时复制开销的只读集合**,它靠的是 ImmutableArray<t></t> 配合手动优化实现,不是开箱即用的 FrozenDictionary。
为什么搜不到 FrozenDictionary<TKey, TValue>?
你遇到的编译错误 The type or namespace name 'FrozenDictionary' could not be found 是正常的。.NET 基础类库(BCL)至今未引入该类型。部分博客或 AI 生成内容把 ImmutableDictionary<tkey tvalue>.ToImmutable()</tkey> 或第三方封装误称为 “FrozenDictionary”,但它们本质仍是每次修改返回新实例的不可变集合,不满足“冻结”所要求的内存布局固化与零分配访问语义。
替代方案:用 ImmutableArray<KeyValuePair<TKey, TValue>> 模拟冻结字典
若你真正需要的是高性能、只读、无 GC 压力的键值查找(比如配置映射表、枚举名称缓存),推荐以下实操路径:
- 用
ImmutableArray.CreateBuilder<keyvaluepair int>></keyvaluepair>预填充所有键值对,容量设准避免扩容 - 调用
builder.ToImmutable()一次性生成最终集合,之后绝不修改 builder - 包装一层只读接口,例如
IReadOnlyDictionary<string int></string>,内部用Array.BinarySearch(需先排序)或预建HashSet<string></string>加速查找 - 避免使用
ImmutableDictionary:10k 条目下内存占用高 40%+,且查找是 O(log n),而排序后数组 + 二分是 O(log n) 且无哈希冲突开销
Excel 行列冻结和 DataGridView 冻结是完全不同的事
别被“冻结”这个词带偏。如果你实际想做的是 Excel 窗口冻结(如首行常驻),那要用 Spire.XLS 或 FreeSpire.XLS 的 Worksheet.FreezePanes(int rowIndex, int columnIndex) 方法:
-
sheet.FreezePanes(2, 1)→ 冻结第 1 行(rowIndex=2 表示“第 2 行之上”的行被冻) -
sheet.FreezePanes(1, 2)→ 冻结第 A 列(columnIndex=2 表示“第 2 列之左”的列被冻) -
sheet.RemovePanes()→ 解除冻结 - 注意:索引从 1 开始,不是 0;且
FreezePanes不是 .NET BCL 方法,必须引用第三方库
真正接近“冻结语义”的原生做法只有 ReadOnlySpan<T> + 静态数组
如果目标是极致性能和确定性内存布局(如热路径查表),最接近“冻结”的方式是:
- 用
static readonly KeyValuePair<string int>[] s_lookupTable = { ... };</string>定义静态只读数组 - 暴露为
ReadOnlySpan<keyvaluepair int>></keyvaluepair>或Memory<keyvaluepair int>></keyvaluepair> - 配合
BinarySearch或Dictionary<tkey tvalue>.TryGetValue</tkey>初始化一次的只读实例(注意:后者仍含哈希表结构) - 绝不要在循环中反复调用
builder.Add(x).ToImmutable()—— 这会触发多次数组拷贝,违背冻结初衷
ImmutableArray<t>.AsReadOnly()</t> 就够了;只有毫秒级响应、百万次/秒查表、且内存敏感的场景,才值得投入精力做静态数组 + Span 优化。其他情况,过度追求“冻结”反而增加维护成本。


















