必须用List和Dictionary而非ArrayList或Hashtable,因泛型集合提供编译期类型检查、避免装箱、消除强制转换;自定义键需实现IEqualityComparer或重写GetHashCode/Equals;初始化推荐new List()或[],查字典用TryGetValue,遍历时删除需用RemoveAll或反向for。
直接用
和
,别碰
或
—— 它们不是“不能用”,而是编译期不检查类型、运行时才报错,徒增调试成本。
为什么必须用
而不是
存什么都能过编译,取出来还得手动
强转,一不小心就
;
在声明时就锁死类型,编译器直接拦住非法操作。
只接受
,加
会红波浪线 + 编译错误
从
取元素不用 cast,直接当
用
值类型(如
)存进
会装箱,频繁操作有性能损耗;
避免装箱
的键必须可比较,且不能为
(引用类型)
当你用自定义类做键,比如
,默认行为是按引用比较 —— 两个内容相同但不同实例的
会被当成不同键。这通常不是你想要的。
C知道
CSDN推出的一款AI技术问答工具
下载
解决方法:让
实现
,或重写
和
如果键是
,它本身已实现比较逻辑,直接用即可
注意:
不允许
键(除非 TKey 是可空引用类型,如
,且启用了 nullable context)
泛型集合初始化和常见误操作
初始化写法影响可读性和 null 安全性,尤其在 .NET 6+ 启用 nullable reference types 后。
推荐写法:
或
(C# 12 空集合字面量)
避免
后再
—— 直接
查不存在的键会抛
,要用
而不是先
再取值(多一次查找)
不要用
循环中调用
—— 会触发
;改用
或反向
循环
泛型集合真正的坑不在语法,而在「什么时候该加约束」—— 比如你写了个泛型方法要对
排序,却忘了加
,编译器不会立刻报错,直到你传入一个没实现该接口的类型才崩。这种延迟暴露的问题,比类型不匹配更难定位。
ListDictionaryArrayListHashtableListArrayListArrayList(int)InvalidCastExceptionListListint"abc"ListstringintArrayListListDictionarynullDictionaryPersonPersonIEqualityComparerGetHashCode()Equals()stringDictionarynullstring?var list = new List(); List list = []; List list = null; list.Add(...)NullReferenceExceptionDictionaryKeyNotFoundExceptionTryGetValue()ContainsKey()foreachRemove()InvalidOperationException: Collection was modifiedlist.RemoveAll(x => x > 10)forTwhere T : IComparable