现在不该用 arraylist,因其存在装箱/拆箱开销、无类型安全、运行时类型错误等缺陷;.net 2.0 起应优先使用泛型 list,性能更高、编译期检查、ide 支持好。

为什么现在不该用 ArrayList?
它确实能存任意类型、动态扩容,但代价是装箱/拆箱和无类型安全——int 存进去再取出来得强制转,一不小心就抛 InvalidCastException。.NET 2.0 起就有了 List<t></t>,性能高、编译期报错、IDE 支持好,ArrayList 早该进历史了。
除非你:
- 维护一个 .NET Framework 1.1 的老项目(真有?)
- 必须跟某个强依赖
ArrayList的旧 API 打交道(比如某些 COM 互操作场景) - 写 demo 演示“泛型之前怎么干”的教学代码
ArrayList 添加元素时的隐式转换陷阱
它不拦你往里塞任何东西:string、DateTime、null 全都接得住。但取的时候,如果记错了类型或顺序,运行时报错没商量。
常见错误现象:
-
foreach (int x in list) { ... }→InvalidCastException,因为里面混了string -
(double)list[0]强转失败,实际存的是int(虽同属数值,但不是同一类型) -
list.Add(42); list.Add("hello");看似没问题,后续遍历逻辑崩得无声无息
实操建议:
- 如果非用不可,加个注释说明“此
ArrayList仅存Customer”,靠人肉约定 - 用
list.GetType().GetGenericArguments()查不了——它根本不是泛型,反射也看不出内容类型 - 宁可用
object[]显式声明,至少意图更直白
替代方案:三行代码迁移到 List<t></t>
99% 的 ArrayList 场景,直接换 List<t></t> 就行,不用改逻辑,只改声明和构造。
对比示例:
ArrayList oldList = new ArrayList();
oldList.Add("a");
oldList.Add("b");
// ✅ 替换成
List<string> newList = new List<string>();
newList.Add("a");
newList.Add("b");</string></string>
关键点:
- 构造函数参数一样(可传容量、可传
IEnumerable<t></t>) - 常用方法名完全一致:
Add、Remove、Contains、ToArray -
newList[0]返回string,不用 cast;类型错误编译期就拦住 - 值类型不装箱,
List<int></int>比ArrayList节省内存且快得多
如果必须和旧代码共存:如何安全地桥接 ArrayList 和 List<t></t>
比如调第三方 DLL 返回 ArrayList,你又不想在业务层处处 cast,那就做一次干净转换。
不要这样写:
foreach (var item in oldList) {
list.Add((MyType)item); // ❌ 运行时才崩
}
推荐做法:
- 用
OfType<t>()</t>安全过滤:var typed = oldList.OfType<mytype>().ToList();</mytype> - 用
Cast<t>()</t>前先确认类型:if (oldList.All(x => x is MyType)) { ... } - 最稳妥:手写循环 +
is判断 +as转换,遇到 null 或类型不符就跳过或报具体日志
注意:ArrayList.CopyTo(array, index) 在目标数组类型不匹配时会抛 ArgumentException,不是 InvalidCastException——这个细节容易查半天。
真正难的不是怎么用 ArrayList,而是判断它是不是真不可替代。多数时候,删掉它比学会它更有价值。










