当前位置: 首页 > news >正文

C# 集合详解:ArrayList 与 List<T>的核心用法与对比

一、C# 集合体系概览

C# 的集合类型主要分布在两个核心命名空间:

  • System.Collections:非泛型集合,适用于.NET 早期版本,代表类型有ArrayListHashtableQueue等;
  • System.Collections.Generic:泛型集合(.NET 2.0+),类型安全且性能更优,代表类型有List<T>Dictionary<TKey, TValue>HashSet<T>等。

其中,ArrayListList<T>作为动态数组的典型实现,是日常开发中最常用的集合类型,也是理解 C# 集合设计思想的关键。

二、ArrayList:非泛型动态数组

2.1 ArrayList 核心特性

ArrayList是 C# 早期的动态数组实现,本质是封装了object[]数组的类,核心特性如下:

  • 动态扩容:底层基于数组实现,初始容量为 0,添加第一个元素时扩容至 4,后续自动按需扩容;
  • 非类型安全:所有元素均以object类型存储,值类型会发生装箱 / 拆箱操作;
  • 灵活存储:允许存储null值、重复元素,支持任意类型的对象;
  • 索引访问:支持数组式的索引器访问,时间复杂度 O (1)。

2.2 ArrayList 常用操作

1. 初始化

ArrayList提供三种初始化方式,适配不同场景:

// 空列表(初始容量0) ArrayList list1 = new ArrayList(); // 指定初始容量(减少扩容次数,提升性能) ArrayList list2 = new ArrayList(100); // 从其他集合初始化 ArrayList list3 = new ArrayList(new int[] { 1, 2, 3 });
2. 元素增删

ArrayList提供丰富的元素操作方法,覆盖单个 / 批量、尾部 / 指定位置的增删需求:

ArrayList list = new ArrayList(); // 1. 添加元素 list.Add("C#"); // 尾部添加单个元素 list.Add(123); // 值类型自动装箱(int → object) list.AddRange(new object[] { 4.5, DateTime.Now }); // 批量添加 list.Insert(1, "插入到索引1的位置"); // 指定索引插入 list.InsertRange(2, new ArrayList { "a", "b" }); // 批量插入 // 2. 删除元素 list.Remove("C#"); // 按值删除第一个匹配项 list.RemoveAt(0); // 按索引删除 list.RemoveRange(1, 2); // 从索引1开始删除2个元素 list.Clear(); // 清空所有元素
3. 元素查找与访问
ArrayList list = new ArrayList { "A", "B", "C", "B" }; // 检查元素是否存在 bool hasB = list.Contains("B"); // true // 查找元素索引 int firstBIndex = list.IndexOf("B"); // 1 int lastBIndex = list.LastIndexOf("B"); // 3 // 索引器访问(需显式类型转换) string item = (string)list[0]; // "A" // 排序后二分查找(需先Sort) list.Sort(); int cIndex = list.BinarySearch("C"); // 2

2.3 ArrayList 的局限性

尽管ArrayList灵活,但存在明显短板:

  • 性能损耗:值类型的装箱 / 拆箱操作增加内存开销和性能消耗;
  • 类型不安全:编译时无法校验元素类型,运行时可能抛出InvalidCastException
  • 现代开发不推荐:仅适用于遗留代码或.NET 1.x 环境,新代码优先使用泛型集合。

三、List<T>:类型安全的泛型动态数组

List<T>ArrayList的泛型替代版本,解决了非泛型集合的类型安全和性能问题,是当前 C# 开发的首选动态数组。

3.1 List<T>核心优势

ArrayList相比,List<T>的核心改进在于:

特性ArrayListList<T>
类型安全非泛型,object 存储泛型,编译时类型校验
性能装箱 / 拆箱损耗无装箱操作,性能更优
内存占用较高(object 引用)更低(直接存储值类型)
错误排查运行时类型转换异常编译时类型错误提示

3.2 List<T>常用操作

1. 初始化与基础操作

// 空列表 List<int> numbers = new List<int>(); // 初始化赋值 List<string> names = new List<string> { "Alice", "Bob" }; // 指定初始容量 List<double> values = new List<double>(10); // 添加元素 numbers.Add(1); numbers.AddRange(new int[] { 2, 3, 4 }); // 访问与修改 int first = numbers[0]; // 无需拆箱 numbers[1] = 10; // 基础查询 int count = numbers.Count; bool has3 = numbers.Contains(3);

2. 高级操作:排序

List<T>Sort方法支持多种排序方式,满足复杂场景需求:

方式 1:默认排序(实现 IComparable<T>)

自定义类型需实现IComparable<T>接口,重写CompareTo方法:

public class Student : IComparable<Student> { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } // 按Id升序排序 public int CompareTo(Student other) { if (this.Id > other.Id) return 1; if (this.Id < other.Id) return -1; return 0; } } // 排序使用 List<Student> students = new List<Student> { new Student { Id = 1, Name = "张三" }, new Student { Id = 3, Name = "李四" }, new Student { Id = 2, Name = "王五" } }; students.Sort(); // 按Id升序排列
方式 2:自定义比较器(IComparer<T>)

适用于多种排序规则的场景,无需修改实体类:

// 按年龄降序的比较器 public class StudentAgeComparer : IComparer<Student> { public int Compare(Student x, Student y) { return y.Age.CompareTo(x.Age); } } // 使用比较器排序 students.Sort(new StudentAgeComparer());
方式 3:Lambda 表达式(Comparison<T>)

适用于临时排序需求,简化代码:

// 按年龄降序排序 students.Sort((x, y) => y.Age.CompareTo(x.Age));

3. 高级操作:查找与转换

List<int> numbers = new List<int> { 1, 2, 3, 4, 5 }; // 查找第一个偶数 int firstEven = numbers.Find(n => n % 2 == 0); // 查找所有偶数 List<int> allEvens = numbers.FindAll(n => n % 2 == 0); // 转换为字符串列表 List<string> strNumbers = numbers.ConvertAll(n => n.ToString()); // 转换为数组 int[] numArray = numbers.ToArray();

四、ArrayList 与 List<T>核心对比

表格

维度ArrayListList<T>
类型系统非泛型(object)泛型(强类型)
性能装箱 / 拆箱损耗无装箱,性能更高
类型安全运行时可能出错编译时类型校验
内存占用较高更低
适用场景遗留代码、混合类型存储现代开发、类型明确的集合
引入版本.NET 1.0.NET 2.0+

五、最佳实践

  1. 优先使用 List<T>:新开发项目中,无论值类型还是引用类型,均推荐使用List<T>,兼顾性能与类型安全;
  2. 避免 ArrayList:仅在维护.NET 1.x 遗留代码或必须存储混合类型时使用ArrayList
  3. 指定初始容量:当已知集合大致大小,初始化时指定容量(如new List<int>(100)),减少自动扩容的性能损耗;
  4. 排序优化:自定义类型排序优先使用IComparer<T>Comparison<T>,避免修改实体类的IComparable<T>实现;
  5. 减少装箱操作:若需存储混合类型,可使用List<object>替代ArrayList,保持泛型特性。

总结

ArrayList作为 C# 早期的动态数组实现,见证了.NET 集合体系的发展;而List<T>作为泛型时代的产物,凭借类型安全、高性能的优势成为现代 C# 开发的首选。理解两者的设计思想与使用差异,不仅能帮助开发者写出更高效的代码,也能深入掌握 C# 类型系统的核心逻辑。在实际开发中,结合场景选择合适的集合类型,才能充分发挥 C# 的语言特性与性能优势。

http://www.jsqmd.com/news/882277/

相关文章:

  • 线性系统理论学懵了?手把手带你推导能控性格拉姆矩阵判据(附详细证明步骤)
  • 数据驱动负载减载:应对电力系统网络攻击的智能稳定控制
  • 【Verilog代码规范引起的国产安路编译器不能识别寄存器】
  • common lisp 张量,矩阵计算库介绍
  • 苏州相城区宠物基地口碑推荐榜单一览 - 品牌排行榜
  • 保姆级教程:在Ubuntu20.04上为ROS2机器人项目配置CUDA11.3与TensorRT推理环境
  • SubCube稀疏注意力架构的优势是什么
  • PHP无参RCE
  • 医疗物联网异常检测:八种机器学习算法实战对比与选型指南
  • Armv9 SME指令集:矩阵运算加速原理与优化实践
  • 量子生成模型:原理、优势与应用场景解析
  • 终极指南:3种简单方法快速重置JetBrains IDE试用期
  • 大麦网抢票神器终极指南:告别黄牛票的Python自动化解决方案
  • ARM ETE协议异常处理与指令追踪技术解析
  • 3分钟快速修复:洛雪音乐六音音源终极解决方案
  • 增强采样与力匹配结合:高效构建高精度粗粒化分子动力学模型
  • 3分钟快速修复洛雪音乐播放问题:六音音源完整指南
  • 音频输入系统——第二周
  • 直接去偏机器学习:用Bregman散度统一因果推断与协变量平衡
  • 基于CNN的遥感影像土地利用分类:从原理到斐济城市扩张监测实践
  • JMeter压测8大实战陷阱:从线程模型到SLA验证
  • 嘉兴GEO优化公司2026年度深度评测选型指南 - 品牌报告
  • 卷积神经网络(CNN)与深度学习视觉应用综述
  • 我用 GPT-5.5 跑了一周行政工作:会议纪要、邮件整理,到底能省多少时间?
  • Windows Audio服务启动失败?除了疑难解答,你还需要检查这些容易被忽略的设置
  • 机器学习优化活性粒子信息引擎:突破热力学极限的非平衡控制
  • 苏州评价高的宠物基地口碑推荐榜单 - 品牌排行榜
  • 基于BERT与LSTM的抽取式新闻摘要实战:从原理到实现
  • BetterJoy:让Switch手柄在PC上完美工作的终极适配工具
  • 2024终极指南:如何用微信红包助手快速抢到所有红包