在C#中,常用的集合主要在:System.Collections
和System.Collections.Generic
命名空间中。
一.System.Collections.Generic
-
List<T> 可以动态调整大小的数组,提供添加、插入、删除、搜索等方法的集合。
- LinkedList<T> 双向链表,允许在列表的任何位置高效地添加或删除元素。在
- Queue<T> 先进先出(FIFO)的集合,用于在集合的末尾添加元素并从开头移除元素。
- Stack<T> 后进先出(LIFO)的集合,用于在集合的顶部添加或移除元素。
- HashSet<T> 一个不包含重复元素的集合,用于高效地检查元素是否存在。
- SortedSet<T> 一个自动排序的集合,其中的元素按照排序顺序存储。
- Dictionary<TKey,TValue> 一个键值对的集合,用于存储键和值之间的映射关系,并根据键高效地检索值。
- SortedDictionary<TKey,TValue> 一个键值对的集合,其中的键按照排序顺序存储.
- IReadOnlyCollection<T> 与IReadOnlyList<T> 表示只读的集合和列表,用于提供对集合内容的只读访问。
- IReadOnlyDictionary<TKey,TValue> 表示只读的键值对集合,用于提供对字典内容的只读访问。
二.System.Collections(不推荐)
-
ArrayList:一个可以动态调整大小的数组,可以存储任何类型的对象。由于非泛型,性能上可能不如泛型集合,且类型安全性较差。
- Hashtable 与 SortedList: 键值对的非泛型集合,与
Dictionary<TKey, TValue>
和SortedDictionary<TKey, TValue>
类似,但同样存在性能和类型安全性的问题
三.System.Collections.Concurrent命名空间的线程安全集合(允许在多线程环境中安全地访问和修改集合)
-
ConcurrentBag<T>:线程安全的无序集合。ConcurrentDictionary<TKey, TValue>:线程安全的键值对集合。
-
ConcurrentDictionary<TKey, TValue>:线程安全的键值对集合。
- ConcurrentQueue<T>:线程安全的先进先出集合。
- ConcurrentStack<T>:线程安全的后进先出集合。
四.其他
-
BitVector32 和 BitVector64:用于存储位信息的紧凑数据结构,常用于表示标志位或开关状态。
- NameValueCollection:一个简单的键值对集合,常用于Web开发中存储查询字符串或表单数据。
五.自定义集合
通过实现集合接口(如 IEnumerable<T>
、ICollection<T>
、IList<T>
等)或继承现有的集合类来创建自定义集合
六.如何选择集合
1.是否需要顺序列表(其中通常在检索元素值后就将该元素丢弃)?
- 在需要的情况下,如果需要先进先出 (FIFO) 行为,请考虑使用 Queue 类或 Queue 泛型类。如果需要后进先出 (LIFO) 行为,请考虑使用 Stack 类或 Stack 泛型类。若要从多个线程进行安全访问,请使用并发版本(ConcurrentQueue 和 ConcurrentStack)。如果要获得不可变性,请考虑不可变版本 ImmutableQueue 和 ImmutableStack。
- 如果不需要,请考虑使用其他集合。
2.是否需要以特定顺序(如先进先出、后进先出或随机)访问元素?
- Queue 类以及 Queue、ConcurrentQueue 和 ImmutableQueue 泛型类都提供 FIFO 访问权限。有关详细信息,请参阅何时使用线程安全集合。
- Stack 类以及 Stack、ConcurrentStack 和 ImmutableStack 泛型类都提供 LIFO 访问权限。有关详细信息,请参阅何时使用线程安全集合。
- LinkedList 泛型类允许从开头到末尾或从末尾到开头的顺序访问。
3.是否需要按索引访问每个元素?
- ArrayList 和 StringCollection 类以及 List 泛型类按从零开始的元素索引提供对其元素的访问。如果要获得不可变性,请考虑不可变泛型版本 ImmutableArray 和 ImmutableList。
- Hashtable、SortedList、ListDictionary 和 StringDictionary 类以及 Dictionary<tkey,tvalue> 和 SortedDictionary<tkey,tvalue> 泛型类按元素的键提供对其元素的访问。此外,还有几个相应类型的不可变版本:ImmutableHashSet、ImmutableDictionary<tkey,tvalue>、ImmutableSortedSet 和 ImmutableSortedDictionary<tkey,tvalue>。
- NameObjectCollectionBase 和 NameValueCollection 类以及 KeyedCollection<tkey,titem> 和 SortedList<tkey,tvalue> 泛型类按从零开始的元素索引或元素的键提供对其元素的访问。
4.是否每个元素都包含一个值、一个键和一个值的组合或一个键和多个值的组合?
- 一个值:使用任何基于 IList 接口或 IList 泛型接口的集合。要获得不可变选项,请考虑 IImmutableList 泛型接口。
- 一个键和一个值:使用任何基于 IDictionary 接口或 IDictionary<tkey,tvalue> 泛型接口的集合。要获得不可变选项,请考虑 IImmutableSet 或 IImmutableDictionary<tkey,tvalue> 泛型接口。
- 带有嵌入键的值:使用 KeyedCollection<tkey,titem> 泛型类。
- 一个键和多个值:使用 NameValueCollection 类。
5.是否需要以与输入方式不同的方式对元素进行排序?
- Hashtable 类按其哈希代码对其元素进行排序。
- SortedList 类以及 SortedList<tkey,tvalue> 和 SortedDictionary<tkey,tvalue> 泛型类按键对元素进行排序。排序顺序的依据为,实现 SortedList 类的 IComparer 接口和实现 SortedList<tkey,tvalue> 和 SortedDictionary<tkey,tvalue> 泛型类的 IComparer 泛型接口。在这两种泛型类型中,虽然 SortedDictionary<tkey,tvalue> 的性能优于 SortedList<tkey,tvalue>,但 SortedList<tkey,tvalue> 占用的内存更少。
- ArrayList 提供了一种 Sort 方法,此方法采用 IComparer 实现作为参数。其泛型对应项(List 泛型类)提供一种 Sort 方法,此方法采用 IComparer 泛型接口的实现作为参数。
6.是否需要快速搜索和信息检索?
- 对于小集合(10 项或更少),ListDictionary 速度比 Hashtable 快。Dictionary<tkey,tvalue> 泛型类提供比 SortedDictionary<tkey,tvalue> 泛型类更快的查找。多线程的实现为 ConcurrentDictionary<tkey,tvalue>。ConcurrentBag 为无序数据提供快速的多线程插入。有关这两种多线程类型的详细信息,请参阅何时使用线程安全集合。
7.是否需要只接受字符串的集合?
- StringCollection(基于 IList)和 StringDictionary(基于 IDictionary)位于 System.Collections.Specialized 命名空间。
- 此外,通过指定其泛型类参数的 String 类,可以使用 System.Collections.Generic 命名空间中的任何泛型集合类作为强类型字符串集合。例如,可以将变量声明为采用 List 或 Dictionary<string,string> 类型。