集合:
Dictionary<(Of <(TKey, TValue>)>) 键值对集合
LinkedList<(Of <(T>)>) 双链表
List<(Of <(T>)>) 动态数组
Queue<(Of <(T>)>) 队列
SortedDictionary<(Of <(TKey, TValue>)>) 有序键值对集合
SortedList<(Of <(TKey, TValue>)>) 类似SortedDictionary, 数据存储结构为二分查找树
Stack<(Of <(T>)>) 栈
以上是范型集合里面的,一般情况下优先用范型的,非范型就不写了,
泛型集合就类似于一个特定类型的数组,但是和集合的概念一样,可以储存非常多的与这个类型相同的对象, 而不需要像数组那样需要指定大小以确保能容纳所有需要存放的对象;
泛型 听起来很高深的一个词,但实际上它的作用很简单,就是提高c#程序的性能。 比如在计算机中经常用到一些数据结构,如队列,链表等,而其中的元素以前一般这么定义:object a=new object(); 这样就带来一个严重的问题,用object来表示元素没有逻辑问题,但每次拆箱、封箱就占用了大量的计算机资源,导致程序性能低下, 而这部分内容恰恰一般都是程序的核心部分,如果使用object,那么程序的表现就比较糟糕。 而使用泛型则很好的解决这个问题,本质就是在编译阶段就告诉编译器,数据结构中元素的种类,既然编译器知道了元素的种类,自然就避免了拆箱、封箱的操作, 从而显著提高c#程序的性能。 比如List<string>就直接使用string对象作为List的元素,而避免使用object对象带来的封箱、拆箱操作,从而提高程序性能。
在.NET FCL为我们提供了很多集合类型,是编程中非常有力的工具。泛型集合主要在System.Collections.Generic名称空间中,而非泛型集合主要在System.Collections,首先抛出结论:如果在C#2.0版本以上,尽量使用泛型集合类,而不使用非泛型集合类。因为,1.泛型编程是从c#2.0开始才被.net支持的。2.泛型集合在性能和类型安全方面优于非泛型集合。
非泛型集合-System.Collections名字空间中的类主要包括ArrayList, Hashtable,Queue,SortedList,Stack等,而泛型集合-System.Collections.Generic中常用的包括List<T>,LinkedList<T>,Queue<T>,Stack<T>。这些都是非常常见的数据结构。
性能问题
下面以ArrayList与List<T>为例说明泛型集合的优点及非泛型集合的缺点。(可以通过Visual Studio的object browser浏览这两个类的方法,属性等)。
例如,有这么一段代码:
1. ArrayList numbers = new ArrayList();
2. numbers.Add(22);
3. numbers.Add(35);
4. int number =(int) numbers[1];
5. Console.WriteLine(number);
这段代码的背后会发生什么呢?首先,ArrayList中将所有元素都看成Object类型的,是引用类型。第一行声明一个ArrayList的对象,第二,三行调用Add方法增加两个整数。
在这个过程中,整数22,35被CLR装箱(boxing)成object类型的,而在第四行访问第二个元素时又被拆箱(unboxing),装箱与拆箱大体上会发生以下过程
1. 在托管堆中非配一个新的object
2. 基于栈(stack-based)的数据必须移动到刚非配的内存区中
3. 当拆箱时,位于堆中的数据又得移动到栈中
4. 堆中无用的数据进行垃圾回收
当涉及大量装箱与拆箱操作时,必然会影响应用程序的性能。而是用泛型的集合类时,比如用
List<int> numbers = new List<int>();代替上述第一行,第四行相应改成
int number = numbers[1];减少了装箱与拆箱的工作,当存在大量数据时,自然可以提高很多性能。
类型安全问题
对于ArrayList,下面的代码编译时时不会报错的。
ArrayList numbers = new ArrayList();
numbers.Add(22);
numbers.Add(35.5);
numbers.Add(true);
for (int i = 0; i < numbers.Count; i++)
{
Console.WriteLine((int)numbers[i]);
}
因为可以将int类型,float等数值类型装箱成object,因此即使ArrayList增加的数据类型不一致。编译器也不会提示错误,但是运行时,会报错。
但是如果是用泛型类型比如List<T>,那么在编译时就会进行类型检查。防止运行时错误。