c# 泛型List的定义、作用、用法
《C# 泛型List的定义、作用、用法》
在C#编程中,泛型(Generics)是.NET Framework 2.0引入的核心特性之一,它通过类型参数化实现了代码的复用性与类型安全性。作为泛型集合的代表,`List
一、List的定义与底层原理
`List
1.1 类型安全机制
泛型的核心优势在于类型安全。例如,以下代码会直接导致编译错误:
List intList = new List();
intList.Add("string"); // 编译错误:无法将字符串隐式转换为int
这种编译期类型检查有效防止了运行时类型异常,而`ArrayList`等非泛型集合则需通过运行时类型转换,存在潜在风险:
ArrayList arrayList = new ArrayList();
arrayList.Add(42);
arrayList.Add("text"); // 允许但危险
int num = (int)arrayList[1]; // 运行时抛出InvalidCastException
1.2 动态扩容实现
`List
List optimizedList = new List(100); // 初始容量100
二、List的核心作用
`List
2.1 类型安全的元素存储
通过泛型参数`T`,`List
class Person { public string Name { get; set; } }
List people = new List {
new Person { Name = "Alice" },
new Person { Name = "Bob" }
};
// people.Add(123); // 编译错误
2.2 动态大小管理
与固定大小的数组不同,`List
List numbers = new List();
Console.WriteLine(numbers.Capacity); // 输出0
numbers.Add(3.14);
Console.WriteLine(numbers.Capacity); // 输出4(默认扩容策略)
2.3 丰富的成员方法
`List
类别 | 典型方法 |
---|---|
添加元素 | Add、AddRange、Insert |
删除元素 | Remove、RemoveAt、RemoveAll、Clear |
查找元素 | Contains、IndexOf、Find、Exists |
排序转换 | Sort、Reverse、ConvertAll |
三、List的典型用法
掌握`List
3.1 元素添加与初始化
创建列表的三种常见方式:
// 方式1:空列表
List list1 = new List();
// 方式2:指定初始容量
List list2 = new List(10);
// 方式3:集合初始化器(C# 3.0+)
List list3 = new List { "C#", "Java", "Python" };
3.2 元素访问与修改
通过索引器或方法访问元素:
List letters = new List { 'A', 'B', 'C' };
char first = letters[0]; // 'A'
letters[1] = 'X'; // 修改第二个元素
Console.WriteLine(string.Join(", ", letters)); // 输出A, X, C
3.3 查找与过滤
使用`Find`系列方法进行条件查询:
class Product {
public string Name { get; set; }
public decimal Price { get; set; }
}
List products = new List {
new Product { Name = "Laptop", Price = 999.99m },
new Product { Name = "Mouse", Price = 19.99m }
};
// 查找第一个价格低于50的产品
Product cheapItem = products.Find(p => p.Price expensiveItems = products.FindAll(p => p.Price > 100);
Console.WriteLine(expensiveItems.Count); // 输出1
3.4 排序与比较
`List
方式1:使用`IComparable
class Student : IComparable {
public string Name { get; set; }
public int Score { get; set; }
public int CompareTo(Student other) {
return this.Score.CompareTo(other.Score);
}
}
List students = new List {
new Student { Name = "Tom", Score = 85 },
new Student { Name = "Jerry", Score = 92 }
};
students.Sort(); // 按Score升序排列
方式2:使用`Comparison
// 按Name降序排列
students.Sort((x, y) => y.Name.CompareTo(x.Name));
// 使用LINQ的OrderBy(需引入System.Linq)
var orderedStudents = students.OrderByDescending(s => s.Score).ToList();
3.5 转换与投影
通过`ConvertAll`方法实现类型转换:
List numbers = new List { 1, 2, 3 };
List stringNumbers = numbers.ConvertAll(n => n.ToString());
Console.WriteLine(string.Join(", ", stringNumbers)); // 输出1, 2, 3
四、List的高级技巧
掌握以下技巧可显著提升代码质量与性能。
4.1 自定义比较器
实现`IComparer
class LengthComparer : IComparer {
public int Compare(string x, string y) {
return x.Length.CompareTo(y.Length);
}
}
List words = new List { "apple", "banana", "kiwi" };
words.Sort(new LengthComparer());
Console.WriteLine(string.Join(", ", words)); // 输出kiwi, apple, banana
4.2 批量操作优化
使用`AddRange`替代多次`Add`调用:
// 低效方式
List slowList = new List();
for (int i = 0; i fastList = new List(array); // 构造函数初始化
// 或
List anotherList = new List();
anotherList.AddRange(array);
4.3 只读视图创建
通过`AsReadOnly()`方法创建不可修改的列表视图:
List mutableList = new List { "A", "B" };
IList readOnlyList = mutableList.AsReadOnly();
try {
readOnlyList.Add("C"); // 抛出NotSupportedException
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
4.4 结构体列表的特殊处理
对于值类型(如结构体),需注意避免不必要的复制:
struct Point { public int X; public int Y; }
List points = new List();
points.Add(new Point { X = 1, Y = 2 });
// 修改元素(需通过索引器)
ref Point firstPoint = ref CollectionsMarshal.AsSpan(points)[0];
firstPoint.X = 10; // .NET 5+的高效修改方式
五、性能优化建议
合理使用`List
- 预分配容量:已知元素数量时,通过构造函数指定初始容量
- 避免中间扩容:频繁添加元素时,手动设置足够大的容量
- 优先使用索引访问:随机访问时索引器比`Find`方法更快
- 慎用删除操作:`RemoveAt`会导致后续元素移动,批量删除考虑重建列表
-
结构体列表注意:大量值类型元素时,考虑使用数组或`Span
`
六、与其它集合类型的对比
特性 | List |
Array | LinkedList |
HashSet |
---|---|---|---|---|
容量调整 | 动态 | 固定 | 动态 | 动态 |
访问速度 | O(1) | O(1) | O(n) | O(1) |
插入/删除 | O(n) | O(n) | O(1) | O(1) |
唯一性 | 允许重复 | 允许重复 | 允许重复 | 唯一 |
排序支持 | 是 | 需手动 | 否 | 否 |
七、实际应用案例
案例1:分页查询实现
public List GetPagedData(List source, int pageIndex, int pageSize) {
return source.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.ToList();
}
// 使用示例
List allData = Enumerable.Range(1, 100).ToList();
var page2 = GetPagedData(allData, 2, 10); // 获取第2页,每页10条
案例2:并行处理大数据集
List largeDataset = GetLargeDataset(); // 假设获取100万条数据
int batchSize = 10000;
var results = new ConcurrentBag();
Parallel.For(0, (largeDataset.Count + batchSize - 1) / batchSize, i => {
int start = i * batchSize;
int end = Math.Min(start + batchSize, largeDataset.Count);
var batch = largeDataset.GetRange(start, end - start);
// 模拟处理
double batchSum = batch.Average();
results.Add(batchSum);
});
Console.WriteLine($"平均值集合: {string.Join(", ", results)}");
八、常见问题解答
Q1:List
A:需要动态增减元素时选`List
Q2:如何实现深拷贝List
A:对于引用类型元素,需手动实现克隆逻辑:
List original = new List { ... };
List copy = original.ConvertAll(p => new Person {
Name = p.Name,
// 复制其他属性...
});
Q3:为什么List
A:`AddRange`内部会一次性计算所需容量,避免多次扩容操作。
Q4:如何高效移除List
A:从后向前删除可避免索引变化问题:
for (int i = list.Count - 1; i >= 0; i--) {
if (ShouldRemove(list[i])) {
list.RemoveAt(i);
}
}
Q5:List
A:不安全。多线程访问需使用锁或并发集合(如`ConcurrentBag
关键词:C#泛型、List定义、类型安全、动态扩容、集合操作、性能优化、泛型集合、元素管理、排序算法、多线程处理
简介:本文系统介绍了C#中泛型List的定义、类型安全机制和动态扩容原理,详细阐述了其在元素存储、大小管理和方法调用方面的核心作用,通过代码示例展示了添加、查找、排序等典型用法,并提供了自定义比较器、批量操作等高级技巧,最后对比了不同集合类型的特性并给出性能优化建议。