Effective C# Item40 : 根据需要选用恰当的集合
本条只针对.NET 1.x,因此不会涉及到泛型,讨论的是不全面的。
.NET为我们提供了很多中类型的集合,每种类型都有自己适用的场景,并没有一种类型可以适用于所有场景。这些集合包括:链表、数组、队列、栈等。所有的集合都实现了ICollection接口,因此,我们可以通过查找ICollection接口的方式,比较快速得到所有集合类型,其中IList和IDictionary两个接口都是派生自ICollection接口,IList是值的集合,其元素通过索引进行访问,例如ArrayList;IDictionary是键/值对的集合,例如HashTable。如果上述两种类型的集合都不能满足你的需求,那么你可以直接从ICollection接口创建自己的集合类型。
在.NET 1.x的年代里,我们最常用的集合类型是数组Array,或者说某种特性类型的数组,之所以最常用,是因为其他类型的集合中的元素都是System.Object类型,在使用时,会遇到频繁的装箱/拆箱操作。在.NET 2.0引入泛型后,其他类型的集合拥有了充分发挥作用的机会。
关于数组,一个注意的事情:如果数组元素是引用类型,那么使用new的方式初始化数组时,并不会初始化数组元素,这时如果访问数组元素,得到的是null,还需要程序在访问时,执行数组元素的实例化操作。
对于多维数组,.NET为我们提供了两种不同类型的数组,一种是“锯齿”形式的多维数组,一种是“普遍”意义上的多维数组,声明方式和遍历方式都有区别,请看以下代码。

1 /// <summary>
2 /// test multi dimension array
3 /// </summary>
4 private static void MultiDimArrayTest()
5 {
6 //锯齿型数组
7 int[][] arrJaggedTest = new int[3][];
8 arrJaggedTest[0] = new int[5];
9 arrJaggedTest[1] = new int[2];
10 arrJaggedTest[2] = new int[4];
11 foreach (int[] arrTemp in arrJaggedTest)
12 {
13 foreach (int nTemp in arrTemp)
14 {
15 Console.Write(nTemp);
16 }
17 }
18 Console.WriteLine();
19 //普通多维数组
20 int[,] arrMulDim = new int[3, 5];
21 foreach (int nTemp in arrMulDim)
22 {
23 Console.Write(nTemp);
24 }
25 }
可以看出,在遍历时,对于“锯齿”形式的多维数组,每一维都需要使用foreach语句,而对于“普遍”意义上的多维数组,直接使用一个foreach就可以对其进行遍历了。
使用数组带来的缺陷:1. 不能动态的调整大小;2. 不能对数组元素执行动态的插入和删除。
为了解决第一个缺陷,.NET为我们提供了ArrayList,它基于数组,但是在内部对其大小进行维护,不需要用户关心;针对上述第二个缺陷,.NET为我们提供了字典类型的数据,这中类型的集合采用HashTable的方式存储Key和Value,我们在查找、添加和删除元素时,都会比较方便。
当我们定义的类型中包含集合时,那么我们应该将集合暴露给用户,有两种方法可以实现这个目的:1. 为类型编写索引器;2. 为类型实现IEnumerable接口。
在实际使用的过程中,采用哪种类型的集合,取决于要执行的操作以及应用程序对空间和速度的整体目标,在大多数情况下,Array类提供了最高效的集合容器(只是针对.NET 1.x来说)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通