C# List
概述
List<T> 是 C# 中最常用的泛型集合之一,它提供了动态数组的功能,可以存储相同类型的元素,并支持多种操作。本文档将全面介绍 List<T> 的所有主要属性和方法。
属性
Count
- 描述: 获取 List 中实际包含的元素数量
- 类型:
int - 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Orange"};
Console.WriteLine(fruits.Count); // 输出: 3Capacity
- 描述: 获取或设置 List 内部数据结构在不调整大小的情况下能够容纳的元素总数
- 类型:
int - 注意: Capacity 总是大于或等于 Count
- 示例:
csharp
List<int> numbers = new List<int>(10);
Console.WriteLine(numbers.Capacity); // 输出: 10
numbers.Capacity = 20; // 显式设置容量方法
添加元素
Add(T item)
- 描述: 将对象添加到 List 的末尾
- 参数:
item: 要添加到 List 末尾的对象
- 时间复杂度: 平摊 O(1)
- 示例:
csharp
List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
// numbers 现在包含 [1, 2]AddRange(IEnumerable<T> collection)
- 描述: 将指定集合的元素添加到 List 的末尾
- 参数:
collection: 应将其元素添加到 List 末尾的集合
- 时间复杂度: O(n),其中 n 是要添加的元素数量
- 示例:
csharp
List<int> numbers = new List<int> {1, 2};
int[] moreNumbers = {3, 4, 5};
numbers.AddRange(moreNumbers);
// numbers 现在包含 [1, 2, 3, 4, 5]Insert(int index, T item)
- 描述: 将元素插入 List 的指定索引处
- 参数:
index: 应插入 item 的从零开始的索引item: 要插入的对象
- 异常: 如果 index 小于 0 或大于 Count,则抛出 ArgumentOutOfRangeException
- 时间复杂度: O(n)
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana"};
fruits.Insert(1, "Orange");
// fruits 现在包含 ["Apple", "Orange", "Banana"]InsertRange(int index, IEnumerable<T> collection)
- 描述: 将集合中的元素插入 List 的指定索引处
- 参数:
index: 应插入新元素的从零开始的索引collection: 应将其元素插入到 List 中的集合
- 时间复杂度: O(n + m),其中 n 是 index 之后的元素数量,m 是要插入的元素数量
- 示例:
csharp
List<int> numbers = new List<int> {1, 5};
int[] moreNumbers = {2, 3, 4};
numbers.InsertRange(1, moreNumbers);
// numbers 现在包含 [1, 2, 3, 4, 5]移除元素
Remove(T item)
- 描述: 从 List 中移除特定对象的第一个匹配项
- 参数:
item: 要从 List 中移除的对象
- 返回值: 如果成功移除 item,则为 true;否则为 false
- 时间复杂度: O(n)
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Orange"};
bool removed = fruits.Remove("Banana"); // removed = true
// fruits 现在包含 ["Apple", "Orange"]RemoveAt(int index)
- 描述: 移除 List 的指定索引处的元素
- 参数:
index: 要移除的元素的从零开始的索引
- 时间复杂度: O(n)
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
numbers.RemoveAt(2); // 移除索引为2的元素(3)
// numbers 现在包含 [1, 2, 4, 5]RemoveAll(Predicate<T> match)
- 描述: 移除与指定的谓词所定义的条件相匹配的所有元素
- 参数:
match: 定义要移除的元素的条件
- 返回值: 从 List 中移除的元素数
- 时间复杂度: O(n)
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5, 6};
int removed = numbers.RemoveAll(x => x % 2 == 0); // 移除所有偶数
// removed = 3 (移除了2,4,6)
// numbers 现在包含 [1, 3, 5]RemoveRange(int index, int count)
- 描述: 从 List 中移除一系列元素
- 参数:
index: 要移除的元素范围的从零开始的起始索引count: 要移除的元素数
- 时间复杂度: O(n)
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5, 6};
numbers.RemoveRange(1, 3); // 从索引1开始移除3个元素
// numbers 现在包含 [1, 5, 6]Clear()
- 描述: 从 List 中移除所有元素
- 时间复杂度: O(1)
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3};
numbers.Clear();
Console.WriteLine(numbers.Count); // 输出: 0查询和操作
Contains(T item)
- 描述: 确定某元素是否在 List 中
- 参数:
item: 要在 List 中定位的对象
- 返回值: 如果在 List 中找到 item,则为 true;否则为 false
- 时间复杂度: O(n)
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Orange"};
bool hasApple = fruits.Contains("Apple"); // true
bool hasGrape = fruits.Contains("Grape"); // falseToArray()
- 描述: 将 List 的元素复制到新数组中
- 返回值: 一个包含 List 元素副本的数组
- 时间复杂度: O(n)
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3};
int[] numbersArray = numbers.ToArray();
// numbersArray 包含 [1, 2, 3]Sort()
- 描述: 使用默认比较器对整个 List 中的元素进行排序
- 时间复杂度: O(n log n) 平均情况,O(n^2) 最坏情况
- 示例:
csharp
List<int> numbers = new List<int> {3, 1, 4, 2};
numbers.Sort();
// numbers 现在包含 [1, 2, 3, 4]Sort(Comparison<T> comparison)
- 描述: 使用指定的 Comparison<T> 对整个 List 中的元素进行排序
- 参数:
comparison: 比较元素时要使用的 Comparison<T>
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Cherry"};
fruits.Sort((x, y) => x.Length.CompareTo(y.Length));
// 按字符串长度排序,结果: ["Apple", "Cherry", "Banana"]Sort(IComparer<T> comparer)
- 描述: 使用指定的比较器对整个 List 中的元素进行排序
- 参数:
comparer: 比较元素时要使用的 IComparer<T> 实现
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Cherry"};
fruits.Sort(StringComparer.OrdinalIgnoreCase);
// 使用不区分大小写的比较器排序Reverse()
- 描述: 将整个 List 中元素的顺序反转
- 时间复杂度: O(n)
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4};
numbers.Reverse();
// numbers 现在包含 [4, 3, 2, 1]IndexOf(T item)
- 描述: 搜索指定的对象,并返回整个 List 中第一个匹配项的从零开始的索引
- 参数:
item: 要在 List 中定位的对象
- 返回值: 如果在整个 List 中找到 item 的第一个匹配项,则为该项的从零开始的索引;否则为 -1
- 时间复杂度: O(n)
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Orange"};
int index = fruits.IndexOf("Banana"); // index = 1
int notFound = fruits.IndexOf("Grape"); // notFound = -1IndexOf(T item, int index)
- 描述: 搜索指定的对象,并从指定索引开始搜索,返回 List 中第一个匹配项的从零开始的索引
- 参数:
item: 要查找的对象index: 从零开始的搜索的起始索引
- 返回值: 找到的第一个匹配项的索引,或 -1
IndexOf(T item, int index, int count)
- 描述: 搜索指定的对象,并从指定索引开始搜索指定数量的元素,返回 List 中第一个匹配项的从零开始的索引
- 参数:
item: 要查找的对象index: 从零开始的搜索的起始索引count: 要搜索的部分中的元素数
LastIndexOf(T item)
- 描述: 搜索指定的对象,并返回整个 List 中最后一个匹配项的从零开始的索引
- 参数:
item: 要在 List 中定位的对象
- 返回值: 如果在整个 List 中找到 item 的最后一个匹配项,则为该项的从零开始的索引;否则为 -1
- 时间复杂度: O(n)
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Orange", "Banana"};
int lastIndex = fruits.LastIndexOf("Banana"); // lastIndex = 3LastIndexOf(T item, int index)
- 描述: 搜索指定的对象,并从指定索引处开始向开始处搜索,返回 List 中最后一个匹配项的从零开始的索引
- 参数:
item: 要查找的对象index: 向后搜索的从零开始的起始索引
LastIndexOf(T item, int index, int count)
- 描述: 搜索指定的对象,并从指定索引处开始向开始处搜索指定数量的元素,返回 List 中最后一个匹配项的从零开始的索引
- 参数:
item: 要查找的对象index: 向后搜索的从零开始的起始索引count: 要搜索的部分中的元素数
Find(Predicate<T> match)
- 描述: 搜索与指定谓词定义的条件匹配的元素,并返回整个 List 中的第一个匹配项
- 参数:
match: 定义要搜索的元素的条件
- 返回值: 找到的第一个匹配项,或类型 T 的默认值
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
int firstEven = numbers.Find(x => x % 2 == 0); // firstEven = 2FindLast(Predicate<T> match)
- 描述: 搜索与指定谓词定义的条件匹配的元素,并返回整个 List 中的最后一个匹配项
- 参数:
match: 定义要搜索的元素的条件
- 返回值: 找到的最后一个匹配项,或类型 T 的默认值
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
int lastEven = numbers.FindLast(x => x % 2 == 0); // lastEven = 4FindAll(Predicate<T> match)
- 描述: 检索与指定谓词定义的条件匹配的所有元素
- 参数:
match: 定义要搜索的元素的条件
- 返回值: 包含所有匹配元素的新 List<T>
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5, 6};
List<int> evenNumbers = numbers.FindAll(x => x % 2 == 0);
// evenNumbers 包含 [2, 4, 6]FindIndex(Predicate<T> match)
- 描述: 搜索与指定谓词定义的条件匹配的元素,并返回整个 List 中第一个匹配项的从零开始的索引
- 参数:
match: 定义要搜索的元素的条件
- 返回值: 第一个匹配项的索引,或 -1
- 示例:
csharp
List<int> numbers = new List<int> {1, 3, 5, 2, 4};
int firstEvenIndex = numbers.FindIndex(x => x % 2 == 0); // firstEvenIndex = 3FindLastIndex(Predicate<T> match)
- 描述: 搜索与指定谓词定义的条件匹配的元素,并返回整个 List 中最后一个匹配项的从零开始的索引
- 参数:
match: 定义要搜索的元素的条件
- 返回值: 最后一个匹配项的索引,或 -1
- 示例:
csharp
List<int> numbers = new List<int> {1, 3, 5, 2, 4};
int lastEvenIndex = numbers.FindLastIndex(x => x % 2 == 0); // lastEvenIndex = 4ForEach(Action<T> action)
- 描述: 对 List 的每个元素执行指定操作
- 参数:
action: 要对 List 的每个元素执行的 Action<T> 委托
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3};
numbers.ForEach(x => Console.WriteLine(x * 2));
// 输出:
// 2
// 4
// 6GetRange(int index, int count)
- 描述: 创建源 List 中元素范围的浅表副本
- 参数:
index: 范围开始处的从零开始的索引count: 范围中的元素数
- 返回值: 包含元素范围的新 List<T>
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
List<int> subList = numbers.GetRange(1, 3);
// subList 包含 [2, 3, 4]BinarySearch(T item)
- 描述: 使用默认比较器在整个已排序的 List 中搜索元素,并返回该元素的从零开始的索引
- 参数:
item: 要查找的对象
- 返回值: 找到 item 的索引,如果没找到则返回负值
- 注意: 调用此方法前 List 必须已排序
- 示例:
csharp
List<int> numbers = new List<int> {1, 3, 5, 7, 9};
int index = numbers.BinarySearch(5); // index = 2
int notFound = numbers.BinarySearch(4); // 返回负值BinarySearch(T item, IComparer<T> comparer)
- 描述: 使用指定的比较器在整个已排序的 List 中搜索元素
- 参数:
item: 要查找的对象comparer: 比较元素时要使用的 IComparer<T> 实现
BinarySearch(int index, int count, T item, IComparer<T> comparer)
- 描述: 使用指定的比较器在已排序 List 的某个元素范围中搜索元素
- 参数:
index: 要搜索的范围的从零开始的起始索引count: 要搜索的范围的长度item: 要查找的对象comparer: 比较元素时要使用的 IComparer<T> 实现
ConvertAll<TOutput>(Converter<T, TOutput> converter)
- 描述: 将当前 List<T> 中的元素转换为另一种类型,并返回包含转换后的元素的列表
- 参数:
converter: 将每个元素从一种类型转换为另一种类型的委托
- 返回值: 包含转换后的元素的新 List<TOutput>
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3};
List<string> strings = numbers.ConvertAll(x => x.ToString());
// strings 包含 ["1", "2", "3"]CopyTo(T[] array)
- 描述: 将整个 List 复制到兼容的一维数组中,从目标数组的开头开始
- 参数:
array: 作为复制目标的一维数组
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3};
int[] array = new int[3];
numbers.CopyTo(array);
// array 现在包含 [1, 2, 3]CopyTo(T[] array, int arrayIndex)
- 描述: 从目标数组的指定索引处开始,将整个 List 复制到兼容的一维数组中
- 参数:
array: 作为复制目标的一维数组arrayIndex: array 中从零开始的索引,从此处开始复制
CopyTo(int index, T[] array, int arrayIndex, int count)
- 描述: 从目标数组的指定索引处开始,将 List 中某个范围的元素复制到兼容的一维数组中
- 参数:
index: 源 List 中从零开始的索引,从此处开始复制array: 作为复制目标的一维数组arrayIndex: array 中从零开始的索引,从此处开始复制count: 要复制的元素数
Exists(Predicate<T> match)
- 描述: 确定 List 是否包含与指定谓词定义的条件匹配的元素
- 参数:
match: 定义要搜索的元素的条件
- 返回值: 如果 List 包含一个或多个与指定谓词定义的条件匹配的元素,则为 true;否则为 false
- 示例:
csharp
List<int> numbers = new List<int> {1, 2, 3, 4, 5};
bool hasEven = numbers.Exists(x => x % 2 == 0); // trueTrueForAll(Predicate<T> match)
- 描述: 确定 List 中的每个元素是否都与指定谓词定义的条件匹配
- 参数:
match: 定义要检查元素的条件
- 返回值: 如果 List 中的每个元素都与指定谓词定义的条件匹配,则为 true;否则为 false
- 示例:
csharp
List<int> numbers = new List<int> {2, 4, 6, 8};
bool allEven = numbers.TrueForAll(x => x % 2 == 0); // true索引器
list[int index]
- 描述: 获取或设置指定索引处的元素
- 参数:
index: 要获取或设置的元素的从零开始的索引
- 异常: 如果 index 小于 0 或大于等于 Count,则抛出 ArgumentOutOfRangeException
- 示例:
csharp
List<string> fruits = new List<string> {"Apple", "Banana", "Orange"};
// 获取元素
string first = fruits[0]; // "Apple"
// 设置元素
fruits[1] = "Grape";
// fruits 现在包含 ["Apple", "Grape", "Orange"]性能考虑
- 随机访问(通过索引)非常快,时间复杂度为 O(1)
- 在列表末尾添加/删除元素通常是 O(1),但如果需要调整容量则为 O(n)
- 在列表中间插入/删除元素是 O(n) 操作
- 搜索未排序列表是 O(n) 操作
- 对大型列表频繁操作时,考虑预先设置 Capacity 以减少重新分配
线程安全
List<T> 不是线程安全的。如果多个线程需要同时访问 List<T>,必须使用锁或其他同步机制来确保线程安全。
最佳实践
- 如果知道最终大小,预先设置 Capacity 可以提高性能
- 对于频繁的插入/删除操作,考虑使用 LinkedList<T>
- 对于只读操作,考虑使用 ReadOnlyCollection<T> 包装器
- 使用 Find 系列方法代替 Where + FirstOrDefault 可以提高性能


