Dictionary 初始化和添加值的正确写法
直接用
new Dictionary<tkey tvalue>()</tkey>创建实例后,必须用
Add()或索引器赋值才能存入键值对。用错方式会导致运行时异常或静默覆盖。
Add(key, value)要求
key不能已存在,否则抛出
ArgumentException用索引器
dict[key] = value会自动插入新项,或覆盖已有键的值 —— 这是多数场景真正需要的操作 初始化时可用集合初始值设定项:
var dict = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } };
安全获取值:不要直接用 dict[key]
访问未知键
对不存在的键使用
dict[key]会触发
KeyNotFoundException(除非值类型有默认值且字典被允许隐式创建,但这是危险行为)。 优先用
TryGetValue(key, out value)—— 返回
bool表示是否存在,同时输出值,无异常、无装箱、性能最优 若只需判断存在性,用
ContainsKey(key),但后续再取值需二次查找,不推荐连用
GetValueOrDefault(key)可返回默认值(如
0或
null),但无法区分“键不存在”和“键存在但值为默认值”两种情况
键类型必须满足相等性和哈希一致性
自定义类作键时,
GetHashCode()和
Equals()必须同步重写,否则
Add()和
TryGetValue()行为不可预测。 字符串、数字、枚举等内置类型可直接用,无需额外处理 若用
record,编译器自动生成合理实现,适合轻量键类型 避免用可变字段参与
GetHashCode()计算 —— 键插入字典后修改该字段,会导致再也找不到这个键
常见错误:null 键和引用类型值的陷阱
Dictionary<tkey tvalue></tkey>允许
null作为键(当
TKey是引用类型),但容易引发空引用异常,尤其在未检查就调用
TryGetValue()后直接使用
out变量时。 若
TKey是引用类型(如
string),
null是合法键,
dict[null] = 42;有效 若
TValue是引用类型,
TryGetValue()成功时
out参数才被赋值;失败时该变量保持原值 —— 别假设它为
null泛型约束
where TKey : notnull可在编译期禁止
null键,推荐在明确不需要 null 键时加上 实际编码中,最易忽略的是键的哈希稳定性与
TryGetValue()的 out 变量生命周期 —— 这两个点一旦出错,问题往往延迟暴露,调试成本远高于初始化时多写一行约束或检查。
