什么是数组
在C#中,数组是一种数据结构,用于存储同一类型的多个元素。数组一旦创建,其大小就是固定的。数组中的元素是通过索引访问的,索引从0开始。
如何创建和使用数组:
-
声明数组:声明数组时,必须指定数组的类型和数组的大小。
int[] myArray = new int[5]; // 创建一个可以存储5个整数的数组
-
初始化数组:可以在声明时或之后初始化数组。
int[] myArray = new int[5] {1, 2, 3, 4, 5}; // 创建并初始化数组
或者
int[] myArray = {1, 2, 3, 4, 5}; // 初始化数组
-
访问数组元素:使用索引访问数组元素。
int firstElement = myArray[0]; // 获取第一个元素 myArray[1] = 10; // 设置第二个元素为10
-
遍历数组:可以使用
for
循环或foreach
循环遍历数组。for(int i = 0; i < myArray.Length; i++) { Console.WriteLine(myArray[i]); }
或者
foreach(int value in myArray) { Console.WriteLine(value); }
数组的优缺点
优点:
-
快速访问:因为数组是索引的,你可以直接通过索引访问元素,这比查找列表或其他集合中的元素要快。
-
固定大小:创建数组后,你不能改变其大小。如果需要不同大小的集合,你可能需要使用列表或其他数据结构。
-
内存连续:数组在内存中是连续存储的,这意味着可以快速进行内存映射。
缺点:
-
大小固定:一旦创建,你不能改变数组的大小,这可能会限制你的灵活性。
-
存储不同类型的数据:数组只能存储一种类型的数据。
-
初始化必要:在使用数组之前,你需要知道其大小并进行初始化。
数组的使用场景
-
存储集合中的数据:数组可以用于存储数据集合,如学生的成绩,商品的价格等。
-
作为函数参数:数组可以作为函数的参数,用于传递多个值。
-
作为返回值:函数可以返回一个数组。
-
多维数组:C# 支持多维数组,适用于表示表格和矩阵等数据结构。
-
数组作为集合:数组可以作为数据结构,如栈、队列或哈希表的元素。
-
数组作为参数创建数组的方法:使用params关键字可以创建接受一个数组类型参数的方法,方便地将一组参数传递给方法。
-
使用LINQ查询数组:数组支持LINQ(Language Integrated Query),可以用来进行查询、过滤和转换数组中的数据。
-
数组复制:使用Array类的Copy方法可以复制数组。
什么是List<T>?
List在C#中是一个泛型类,位于System.Collections.Generic命名空间下。List<T>是一个动态数组,用于存储和操作一组元素的集合,其中T是元素的类型。List<T>允许在数组末尾添加、删除、搜索和排序元素,提供了更灵活和方便的操作方法
List<T>的基本操作
- 添加元素:可以使用
Add(T item)
方法将对象添加到列表中,或者使用AddRange(IEnumerable<T> collection)
方法添加集合中的元素到列表中1。 - 插入元素:使用
Insert(int index, T item)
方法在指定位置插入元素1。 - 删除元素:可以使用
Remove(T item)
移除特定的对象,RemoveAt(int index)
移除指定索引处的元素,RemoveAll(Predicate<T> match)
移除所有匹配条件的元素,或者使用Clear()
移除所有元素13。 - 查找元素:使用
Contains(T item)
判断是否包含特定的对象,IndexOf(T item)
返回对象的索引,FindIndex(Predicate<T> match)
返回匹配特定条件的元素的索引,或者Find(Predicate<T> match)
返回匹配特定条件的第一个元素13。 - 排序:可以使用
Sort()
对列表进行排序,或者使用Reverse()
反转列表中元素的顺序1。 - 转换和复制:使用
ToArray()
将列表转换为数组,或者使用CopyTo(T[] array)
将列表中的元素复制到一个新的数组中1。 - 统计和求和:使用
Sum(Func<T, int> selector)
计算集合中元素的和,或者使用Average(Func<T, int> selector)
计算集合中元素的平均值1。
List<T>的底层原理
List的底层实现是基于数组。当创建一个列表时,会初始化一个数组来存储元素。列表会自动管理数组的大小,并在需要时进行扩展或收缩。当列表的元素数量达到数组的容量时,列表会创建一个更大的数组,并将元素从旧数组复制到新数组中3。这种动态管理的特性使得List非常适合用于存储和管理动态数据集合。
List<T>的优缺点
优点:
-
动态大小:List的大小可以动态增加或减少,以适应添加或移除元素的需求。
-
简单的API:List提供了一组直观、易用的方法来执行常见操作,如添加、移除、排序和搜索元素。
-
泛型支持:List允许你指定存储在其中的数据类型,这提供了类型安全和更好的性能。
-
与LINQ集成:List可以很容易地与LINQ(语言集成查询)一起使用,以进行复杂的查询和转换操作。
-
与其他集合类型的互操作性:List可以与其他集合类型(如数组和ArrayList)互操作。
缺点:
-
性能:对于频繁的元素插入和删除操作,List的性能可能不如数组。
-
索引访问:与数组相比,通过索引访问List中间元素的速度较慢。
List<T>的使用场景
-
创建和初始化List:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
-
添加元素到List:
numbers.Add(6);
-
从List中移除元素:
numbers.Remove(4);
-
遍历List中的元素:
foreach (int number in numbers) { Console.WriteLine(number); }
-
查找特定元素的索引:
int index = numbers.IndexOf(3);
-
在特定位置插入元素:
numbers.Insert(2, 99);
-
使用条件查询创建List的子集:
List<int> evenNumbers = numbers.FindAll(n => n % 2 == 0);
-
对List进行排序:
numbers.Sort();
-
使用LINQ查询List:
var sum = numbers.Sum();
-
清空List:
numbers.Clear();
数组与List<T>的区别
-
大小限制:数组的大小是固定的,一旦创建,你不能改变它的大小。而
List<T>
是可扩展的,你可以添加或移除元素,而不需要指定数组的大小。 -
类型转换:数组可以转换为
List<T>
,但不能直接转换为其他类型的数组(除非使用反射)。反之,List<T>
可以轻松转换为数组。 -
性能:在性能上,数组通常会略胜一筹,因为
List<T>
在添加或移除元素时会进行内部的边界检查和内存重分配。 -
索引器:数组使用从0开始的索引器,而
List<T>
也是从0开始的,但List<T>
还提供了一个索引器,可以动态增加或减少。