文章目录
-
- 与非泛型集合相比
- **核心接口**
-
- IEnumerable<T>
- IEnumerator<T>
- ICollection<T>
- IList<T>
- [IDictionary<TKey, TValue>](#IDictionary<TKey, TValue>)
- **常用泛型集合类**
-
- List<T>
- [Dictionary<TKey, TValue>](#Dictionary<TKey, TValue>)
- HashSet<T>
- Queue<T>
- Stack<T>
- [SortedList<TKey, TValue>](#SortedList<TKey, TValue>)
- LinkedList<T>
- **其他重要的泛型接口**
- **总结**
System.Collections.Generic 命名空间是 .NET Framework 和 .NET (Core) 中非常重要的一个命名空间。它引入了泛型集合的概念,
与非泛型集合相比
与 System.Collections 中的非泛型集合相比,泛型集合具有以下关键优势
- 类型安全 (Type Safety):
在编译时就能检查集合中元素的类型,避免了运行时的类型转换异常 (InvalidCastException)。
- 性能提升 (Performance Improvement)
由于避免了值类型和引用类型之间的装箱(boxing)和拆箱(unboxing)操作,性能通常更高。
- 代码可读性和可维护性增强 (Improved Code Readability and Maintainability)
通过指定集合中元素的类型,代码意图更加清晰。
下面将介绍 System.Collections.Generic 命名空间中一些最常用和重要的接口和类,并给出相应的 C# 示例。
核心接口
IEnumerable
定义了用于遍历泛型集合的迭代器。它是所有泛型集合的基础接口,支持 foreach 循环。
csharp
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
示例:
csharp
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
foreach (string name in names)
{
Console.WriteLine(name);
}
IEnumerator
支持在泛型集合上进行简单迭代,并提供对当前类型化元素的访问。
csharp
public interface IEnumerator<out T> : IEnumerator, IDisposable
{
new T Current { get; }
}
示例 (通常不直接使用,而是通过 IEnumerable.GetEnumerator() 获取):
csharp
List<int> numbers = new List<int> { 10, 20, 30 };
IEnumerator<int> enumerator = numbers.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
ICollection
继承自 IEnumerable,定义了泛型集合的大小、枚举器和同步的基本操作。
csharp
public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
int Count { get; }
bool IsReadOnly { get; }
void Add(T item);
void Clear();
bool Contains(T item);
void CopyTo(T[] array, int arrayIndex);
bool Remove(T item);
}
示例 (以 List 为例):
csharp
List<double> prices = new List<double>();
prices.Add(9.99);
prices.Add(19.99);
Console.WriteLine($"价格数量: {prices.Count}");
Console.WriteLine($"是否只读: {prices.IsReadOnly}");
bool containsTen = prices.Contains(10.00);
Console.WriteLine($"是否包含 10.00: {containsTen}");
double[] priceArray = new double[prices.Count];
prices.CopyTo(priceArray, 0);
prices.Remove(9.99);
prices.Clear();
IList
继承自 ICollection,表示可通过索引单独访问的对象的泛型集合。
csharp
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
{
T this[int index] { get; set; }
int IndexOf(T item);
void Insert(int index, T item);
void RemoveAt(int index);
}
示例 (List 实现了 IList):
csharp
List<string> colors = new List<string> { "Red", "Green", "Blue" };
Console.WriteLine($"第二个颜色: {colors[1]}");
colors[1] = "Yellow";
colors.Insert(0, "Purple");
int blueIndex = colors.IndexOf("Blue");
Console.WriteLine($"蓝色索引: {blueIndex}");
colors.RemoveAt(3);
IDictionary<TKey, TValue>
继承自 ICollection<KeyValuePair<TKey, TValue>>,表示键/值对的泛型集合。
csharp
public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
{
ICollection<TKey> Keys { get; }
ICollection<TValue> Values { get; }
TValue this[TKey key] { get; set; }
void Add(TKey key, TValue value);
bool ContainsKey(TKey key);
bool Remove(TKey key);
bool TryGetValue(TKey key, out TValue value);
}
示例 (Dictionary<TKey, TValue> 实现了 IDictionary<TKey, TValue>):
csharp
Dictionary<string, int> ages = new Dictionary<string, int>();
ages.Add("Alice", 30);
ages["Bob"] = 25;
Console.WriteLine($"Alice 的年龄: {ages["Alice"]}");
bool hasCharlie = ages.ContainsKey("Charlie");
Console.WriteLine($"是否包含 Charlie: {hasCharlie}");
int bobAge;
if (ages.TryGetValue("Bob", out bobAge))
{
Console.WriteLine($"Bob 的年龄 (TryGetValue): {bobAge}");
}
ages.Remove("Alice");
常用泛型集合类
List
表示一个可使用索引访问的对象的强类型化列表。它提供了动态数组的功能,可以根据需要自动调整大小。
csharp
List<int> scores = new List<int>();
scores.Add(85);
scores.Add(92);
scores.Sort();
foreach (int score in scores)
{
Console.WriteLine(score);
}
Dictionary<TKey, TValue>
表示一个键/值对的集合,这些键是唯一的。它提供了快速的基于键的查找。
csharp
Dictionary<string, string> countryCodes = new Dictionary<string, string>();
countryCodes.Add("China", "CN");
countryCodes["United States"] = "US";
Console.WriteLine($"中国的代码: {countryCodes["China"]}");
HashSet
表示一组唯一的元素。它提供了高效的集合运算,如并集、交集、差集等。
csharp
HashSet<string> uniqueNames = new HashSet<string>();
uniqueNames.Add("Alice");
uniqueNames.Add("Bob");
uniqueNames.Add("Alice"); // 不会重复添加
Console.WriteLine($"唯一名字数量: {uniqueNames.Count}");
bool containsBob = uniqueNames.Contains("Bob");
Console.WriteLine($"是否包含 Bob: {containsBob}");
Queue
表示对象的先进先出 (FIFO) 集合。
csharp
Queue<string> messageQueue = new Queue<string>();
messageQueue.Enqueue("Message 1");
messageQueue.Enqueue("Message 2");
string firstMessage = messageQueue.Dequeue();
Console.WriteLine($"出队: {firstMessage}");
Console.WriteLine($"队列中剩余数量: {messageQueue.Count}");
string peekMessage = messageQueue.Peek();
Console.WriteLine($"队首元素 (不移除): {peekMessage}");
Stack
表示对象的后进先出 (LIFO) 集合。
csharp
Stack<int> callStack = new Stack<int>();
callStack.Push(10);
callStack.Push(20);
int topElement = callStack.Pop();
Console.WriteLine($"出栈: {topElement}");
Console.WriteLine($"栈中剩余数量: {callStack.Count}");
int peekElement = callStack.Peek();
Console.WriteLine($"栈顶元素 (不移除): {peekElement}");
SortedList<TKey, TValue>
表示根据键进行排序的键/值对集合。
csharp
SortedList<string, int> studentGrades = new SortedList<string, int>();
studentGrades.Add("Charlie", 95);
studentGrades.Add("Alice", 88);
studentGrades.Add("Bob", 92);
foreach (KeyValuePair<string, int> entry in studentGrades)
{
Console.WriteLine($"{entry.Key}: {entry.Value}"); // 输出会按字母顺序排序
}
LinkedList
表示一个双向链表。它允许在列表中任何位置进行高效的插入和删除操作。
csharp
LinkedList<string> linkedList = new LinkedList<string>();
linkedList.AddLast("Node 1");
LinkedListNode<string> node2 = linkedList.AddLast("Node 2");
linkedList.AddBefore(node2, "New Node");
foreach (string node in linkedList)
{
Console.WriteLine(node);
}
其他重要的泛型接口
IComparer
定义了比较同一类型的两个对象的方法,用于自定义排序逻辑。
csharp
public class PersonComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x.Name.CompareTo(y.Name);
}
}
class Person
{
public string Name { get; set; }
}
List<Person> people = new List<Person> { new Person { Name = "Bob" }, new Person { Name = "Alice" } };
people.Sort(new PersonComparer());
foreach (Person person in people)
{
Console.WriteLine(person.Name); // 输出: Alice, Bob
}
IEqualityComparer
定义了确定两个对象是否相等以及为对象生成哈希代码的方法,用于自定义集合中的相等性比较(例如在 Dictionary<TKey, TValue> 和 HashSet 中)。
csharp
public class CaseInsensitiveStringEqualityComparer : IEqualityComparer<string>
{
public bool Equals(string x, string y)
{
return string.Equals(x, y, StringComparison.OrdinalIgnoreCase);
}
public int GetHashCode(string obj)
{
return obj?.ToLowerInvariant().GetHashCode() ?? 0;
}
}
HashSet<string> uniqueNamesIgnoreCase = new HashSet<string>(new CaseInsensitiveStringEqualityComparer());
uniqueNamesIgnoreCase.Add("Alice");
uniqueNamesIgnoreCase.Add("alice"); // 不会重复添加
Console.WriteLine($"不区分大小写的唯一名字数量: {uniqueNamesIgnoreCase.Count}"); // 输出: 1
总结
System.Collections.Generic 命名空间提供了强大且类型安全的集合类和接口,是 .NET 开发中处理数据集合的首选方式。理解这些核心接口和常用的集合类的特性和适用场景,能够帮助你编写更高效、更安全、更易于维护的代码。在选择集合类型时,请根据你的具体需求(例如,是否需要索引访问、是否需要唯一元素、是否需要排序、频繁的插入/删除操作等)进行选择。