深入理解C#中的集合类型:从基础到高级应用

在C#编程中,集合(Collections) 是存储和管理一组数据的重要数据结构。无论是简单的数组还是复杂的键值对存储,C#提供了丰富的集合类型来满足不同的需求。本文将全面介绍C#中的各种集合类型,包括非泛型集合、泛型集合、并发集合和不可变集合,并分析它们的适用场景、性能特点以及最佳实践。

深入理解C#中的集合类型:从基础到高级应用_第1张图片

1. 集合类型概述

在C#中,集合类型主要分为以下几类:

  1. 非泛型集合(System.Collections):早期版本提供的集合,可以存储任意类型的对象,但缺乏类型安全。

  2. 泛型集合(System.Collections.Generic):类型安全的集合,性能更优,推荐使用。

  3. 并发集合(System.Collections.Concurrent):线程安全的集合,适用于多线程环境。

  4. 不可变集合(System.Collections.Immutable):一旦创建就不能修改的集合,适用于函数式编程和并行计算。

2. 非泛型集合(System.Collections)

非泛型集合可以存储任何类型的对象(object),但由于它们不提供编译时类型检查,可能导致运行时错误。主要类型包括:

(1)ArrayList(动态数组)

  • 类似于数组,但可以动态调整大小。

  • 存储的是object类型,需要拆箱和装箱操作,影响性能。

ArrayList list = new ArrayList();
list.Add(10);        // 存储整数
list.Add("Hello");   // 存储字符串
int num = (int)list[0];  // 需要显式转换

(2)Hashtable(哈希表)

  • 基于键值对存储,使用哈希算法提高查找速度。

  • 键和值都是object类型,存在类型安全问题。

Hashtable table = new Hashtable();
table.Add("Name", "Alice");
table.Add("Age", 25);
string name = (string)table["Name"];  // 需要类型转换

(3)Queue(队列)

  • 先进先出(FIFO) 结构,适用于任务调度。

Queue queue = new Queue();
queue.Enqueue("Task1");
queue.Enqueue("Task2");
string task = (string)queue.Dequeue();  // 返回 "Task1"

(4)Stack(栈)

  • 后进先出(LIFO) 结构,适用于撤销操作、递归算法等。

Stack stack = new Stack();
stack.Push("Item1");
stack.Push("Item2");
string item = (string)stack.Pop();  // 返回 "Item2"

(5)SortedList(排序列表)

  • 按键排序的键值对集合,类似于Hashtable,但保持有序。

SortedList sortedList = new SortedList();
sortedList.Add("Zebra", 100);
sortedList.Add("Apple", 200);
// 遍历时按键排序:Apple → Zebra
非泛型集合的缺点
  • 类型不安全:需要手动类型转换,可能导致运行时错误。

  • 性能较低:由于使用object,涉及拆箱/装箱操作。

  • 推荐替代方案:尽量使用泛型集合(如ListDictionary)。

3. 泛型集合(System.Collections.Generic)

泛型集合在C# 2.0引入,提供了类型安全和高性能的数据存储方式。常用类型包括:

(1)List(动态数组)

  • 类似于ArrayList,但类型安全,性能更好。

List names = new List();
names.Add("Alice");
names.Add("Bob");
string first = names[0];  // 无需类型转换

(2)Dictionary(字典)

  • 基于哈希表的键值对集合,查找速度极快(O(1))。

Dictionary employees = new Dictionary();
employees.Add(1, "John");
employees.Add(2, "Mary");
string name = employees[2];  // 返回 "Mary"

(3)Queue(泛型队列)

  • 类型安全的FIFO结构。

Queue numbers = new Queue();
numbers.Enqueue(10);
numbers.Enqueue(20);
int firstNum = numbers.Dequeue();  // 返回 10

(4)Stack(泛型栈)

  • 类型安全的LIFO结构。

Stack stack = new Stack();
stack.Push("First");
stack.Push("Second");
string top = stack.Pop();  // 返回 "Second"

(5)HashSet(哈希集合)

  • 存储唯一元素,适用于去重操作。

HashSet uniqueNumbers = new HashSet();
uniqueNumbers.Add(1);
uniqueNumbers.Add(1);  // 不会重复添加
Console.WriteLine(uniqueNumbers.Count);  // 输出 1

(6)LinkedList(双向链表)

  • 支持高效插入和删除,但随机访问较慢(O(n))。

LinkedList linkedList = new LinkedList();
linkedList.AddLast("A");
linkedList.AddLast("B");
linkedList.AddFirst("C");  // 链表顺序:C → A → B
泛型集合的优势
  • 类型安全:编译时检查类型,减少运行时错误。

  • 性能更高:避免拆箱/装箱操作。

  • 推荐使用:在大多数情况下,优先选择泛型集合。

4. 并发集合(System.Collections.Concurrent)

在多线程环境下,普通集合可能引发竞争条件(Race Condition)。C#提供了线程安全的并发集合:

(1)ConcurrentBag(线程安全无序集合)

  • 适用于多线程环境下的数据存储。

ConcurrentBag bag = new ConcurrentBag();
Parallel.For(0, 10, i => bag.Add(i));

(2)ConcurrentDictionary(线程安全字典)

  • 支持并发读写。

ConcurrentDictionary dict = new ConcurrentDictionary();
dict.TryAdd("Key1", 100);
dict.TryUpdate("Key1", 200, 100);  // 更新值

(3)BlockingCollection(阻塞集合)

  • 适用于生产者-消费者模式,支持限制集合大小。

BlockingCollection queue = new BlockingCollection(boundedCapacity: 10);
// 生产者线程
Task.Run(() => { queue.Add(1); });
// 消费者线程
Task.Run(() => { int item = queue.Take(); });
适用场景
  • 多线程编程:如任务队列、并行计算。

  • 避免锁竞争:比手动加锁(lock)更高效。

5. 不可变集合(System.Collections.Immutable)

不可变集合在创建后不能被修改,适用于函数式编程和高并发场景。

(1)ImmutableList(不可变列表)

ImmutableList immutableList = ImmutableList.Create("A", "B");
ImmutableList newList = immutableList.Add("C");  // 返回新列表,原列表不变

(2)ImmutableDictionary(不可变字典)

ImmutableDictionary dict = ImmutableDictionary.Create();
dict = dict.Add(1, "One");
dict = dict.SetItem(1, "NewOne");  // 返回新字典
适用场景
  • 多线程安全:无需锁机制,天然线程安全。

  • 函数式编程:避免副作用(Side Effects)。

6. 如何选择合适的集合类型?

需求 推荐集合
动态数组 List
键值对存储 Dictionary
先进先出(FIFO) Queue
后进先出(LIFO) Stack
去重存储 HashSet
多线程安全 ConcurrentDictionary
不可变数据 ImmutableList

7. 总结

C#提供了丰富的集合类型,适用于不同的应用场景:

  1. 非泛型集合(已过时,不推荐使用)。

  2. 泛型集合(推荐,类型安全且高效)。

  3. 并发集合(适用于多线程)。

  4. 不可变集合(适用于函数式编程和高并发)。

在实际开发中,应根据性能、线程安全和数据访问模式选择合适的集合类型。泛型集合(如ListDictionary)是最常用的选择,而并发集合和不可变集合则适用于特定场景。

希望本文能帮助你更好地理解C#集合类型,并在项目中做出更优的选择!

你可能感兴趣的:(C#,c#,开发语言)