# C#中的数组:从基础到高级应用的全面解析
数组作为C#编程语言中最基础且重要的数据结构之一,贯穿于从简单数据存储到复杂算法实现的各个场景。本文将从数组的基本概念出发,逐步深入探讨其声明、初始化、访问、遍历、排序及多维数组等高级特性,并结合实际案例展示数组在.NET开发中的核心应用。
## 一、数组的基本概念与声明数组是一种固定大小的、类型安全的容器,用于存储相同类型的元素集合。其核心特性包括:元素类型统一、长度固定(创建后不可变)、通过索引快速访问。
### 1.1 数组的声明语法C#中数组的声明需指定元素类型和维度,语法格式为:
元素类型[] 数组名; // 一维数组
元素类型[,] 数组名; // 二维数组
元素类型[,,] 数组名; // 三维数组
示例:
int[] numbers; // 声明一个整型一维数组
string[,] names; // 声明一个字符串二维数组
### 1.2 数组的初始化方式
C#提供多种初始化数组的方法,包括显式初始化、隐式类型推断初始化及通过`new`关键字创建。
#### 显式初始化int[] primes = new int[5] { 2, 3, 5, 7, 11 }; // 指定长度并初始化
string[] colors = { "Red", "Green", "Blue" }; // 隐式推断长度
#### 隐式类型数组(C# 3.0+)
var dynamicArray = new[] { 1.0, 2.5, 3.7 }; // 编译器推断为double[]
#### 空数组初始化
int[] emptyArray = new int[0]; // 创建长度为0的数组
## 二、数组的核心操作
数组的操作涵盖访问、修改、遍历及常用方法调用,这些操作是数组使用的基础。
### 2.1 数组元素的访问与修改通过索引(从0开始)访问或修改数组元素:
int[] scores = { 90, 85, 77 };
Console.WriteLine(scores[0]); // 输出:90
scores[1] = 88; // 修改第二个元素
### 2.2 数组的遍历方法
#### for循环遍历
for (int i = 0; i
#### foreach循环遍历(更简洁)
foreach (int score in scores)
{
Console.WriteLine(score);
}
### 2.3 数组的常用属性与方法
| 属性/方法 | 说明 | 示例 |
|---------|------|------|
| `Length` | 获取数组长度 | `int len = scores.Length;` |
| `Rank` | 获取数组维度 | `int dim = matrix.Rank;` |
| `CopyTo` | 复制到目标数组 | `scores.CopyTo(destination, 0);` |
| `Clone` | 创建浅拷贝 | `int[] copy = (int[])scores.Clone();` |
## 三、多维数组与锯齿数组
C#支持多维数组(矩形)和锯齿数组(不规则),适用于复杂数据建模。
### 3.1 多维数组(矩形数组)声明并初始化二维数组:
int[,] matrix = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };
// 访问元素
int value = matrix[1, 0]; // 输出:3
### 3.2 锯齿数组(数组的数组)
每行长度可不同的数组结构:
int[][] jaggedArray = new int[3][];
jaggedArray[0] = new int[] { 1, 2 };
jaggedArray[1] = new int[] { 3, 4, 5 };
jaggedArray[2] = new int[] { 6 };
// 访问元素
int item = jaggedArray[1][2]; // 输出:5
## 四、数组的排序与搜索
C#提供`Array`类的静态方法对数组进行排序和搜索,极大简化操作。
### 4.1 数组排序 #### 升序排序int[] unsorted = { 5, 2, 8, 1 };
Array.Sort(unsorted); // 结果:{1, 2, 5, 8}
#### 降序排序(结合`Reverse`)
Array.Sort(unsorted);
Array.Reverse(unsorted); // 结果:{8, 5, 2, 1}
#### 自定义对象排序
实现`IComparable`接口或使用`Comparison`委托:
public class Person : IComparable
{
public string Name { get; set; }
public int Age { get; set; }
public int CompareTo(Person other)
{
return this.Age.CompareTo(other.Age);
}
}
Person[] people = { ... };
Array.Sort(people);
### 4.2 数组搜索
#### 二分查找(需已排序)
int[] sorted = { 1, 3, 5, 7 };
int index = Array.BinarySearch(sorted, 5); // 返回:2
#### 线性搜索
int index = Array.FindIndex(unsorted, x => x == 8); // 返回:2
## 五、数组在实际开发中的应用
### 5.1 参数传递与修改
数组作为引用类型,方法内修改会影响原数组:
void ModifyArray(int[] arr)
{
arr[0] = 100;
}
int[] data = { 1, 2, 3 };
ModifyArray(data);
Console.WriteLine(data[0]); // 输出:100
### 5.2 数组与LINQ的结合
使用LINQ查询数组:
int[] numbers = { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0); // {2, 4}
### 5.3 数组的性能优化
- **避免频繁扩容**:预先分配足够空间。
- **使用`Span访问超出索引范围的元素会抛出`IndexOutOfRangeException`:
try
{
int[] arr = { 1, 2 };
Console.WriteLine(arr[3]); // 抛出异常
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine($"错误:{ex.Message}");
}
### 7.2 数组排序稳定性
`Array.Sort`使用快速排序(不稳定),需稳定排序时可用LINQ的`OrderBy`:
var ordered = people.OrderBy(p => p.Age).ToList();
### 7.3 多维数组与锯齿数组的选择
- **多维数组**:数据结构规则(如矩阵计算)。
- **锯齿数组**:每行长度不同(如稀疏矩阵)。
## 八、高级主题:数组与指针(不安全代码)
在需要极致性能的场景,可使用`unsafe`代码和指针操作数组:
unsafe
{
int[] arr = { 10, 20, 30 };
fixed (int* p = arr)
{
int* ptr = p;
Console.WriteLine(*ptr); // 输出:10
*ptr = 100; // 修改第一个元素
}
}
## 九、总结与最佳实践
1. **优先使用数组**:当数据大小固定且类型统一时。
2. **避免过度设计**:简单场景无需使用复杂集合。
3. **注意边界检查**:始终验证索引范围。
4. **结合现代特性**:如LINQ、`Span关键词:C#数组、多维数组、锯齿数组、数组排序、数组搜索、LINQ与数组、不安全代码、数组性能
简介:本文全面解析C#中数组的核心概念与操作,涵盖声明初始化、多维数组、排序搜索、实际开发应用及性能优化,结合代码示例与对比分析,帮助开发者高效使用数组并避免常见陷阱。