SortedDictionary 是基于红黑树的独立实现,O(log n) 插入/查找,不支持重复键;需根据键类型是否实现 IComparable 决定是否传 IComparer;Add 抛异常而索引器覆盖写入;Keys 不支持随机访问;与 Dictionary/SortedList 语义和性能边界明确。

SortedDictionary
初始化时要不要传 IComparer?
默认情况下,SortedDictionary<string int></string> 会用 StringComparer.Ordinal 比较键;SortedDictionary<int string></int> 用 Comparer<int>.Default</int>(即数值大小)。如果你的键类型没实现 IComparable<t></t>,或者需要自定义顺序(比如忽略大小写、按长度排序),就必须显式传入 IComparer<tkey></tkey>:
new SortedDictionary<string int>(StringComparer.OrdinalIgnoreCase)</string>new SortedDictionary<string int>(Comparer<string>.Create((a, b) => a.Length.CompareTo(b.Length)))</string></string>
漏传比较器且 TKey 不可比较,会在运行时报 ArgumentException:“Failed to compare two elements in the array.”
Add 和索引器赋值行为完全不同
Add() 遇到已存在键直接抛 ArgumentException;而用 dict[key] = value 是“覆盖写入”,不会报错:
var dict = new SortedDictionary<string, int>();
dict.Add("a", 1); // OK
dict.Add("a", 2); // 抛 ArgumentException
dict["a"] = 2; // OK,覆盖原值
这个差异常被误认为“Add 更安全”,其实它只在你**明确拒绝覆盖**时才有意义。多数业务逻辑里,用索引器更自然;若真要防误覆盖,应先用 ContainsKey() 或 TryGetValue() 判断。
遍历时 Keys/Values 属性不是 List,不能直接索引
dict.Keys 返回的是 SortedDictionary<tkey>.KeyCollection</tkey>,它实现了 IEnumerable<tkey></tkey>,但**不支持 keys[0] 这种随机访问**:
-
dict.Keys.First()可取最小键(O(log n)) -
dict.Keys.Last()可取最大键(O(log n)) -
dict.Keys.ToList()[0]会强制全部转 List,O(n),别这么干
如果需要按序取第 N 个键,用 dict.Skip(N).FirstOrDefault(),但注意这仍是 O(n) —— 红黑树不支持 O(1) 下标访问,这是和 SortedList 的关键区别。
和 Dictionary / SortedList 混用时最易踩坑
三者接口相似,但语义和性能边界清晰:
- 用
Dictionary:只关心 O(1) 查找、不care顺序、允许频繁增删 - 用
SortedDictionary:需要按键动态有序 + 高频插入/删除(尤其数据非预排序) - 用
SortedList:数据一次性加载完、后续只读或少量修改、内存敏感
把 Dictionary 强转成 SortedDictionary 会编译失败;用 LINQ 的 OrderBy() 对已有 Dictionary 排序,返回的是新序列,不是可变集合——这点容易在调试时误以为“排序生效了”,实际原字典完全没变。


















