🚀 C# 数组(Array)详解:定义、初始化、遍历、内存原理与面试常问
📌 数组是 C# 中最基础的数据结构,也是后续学习集合(List、Dictionary、LINQ)的根基。
一、什么是数组?
数组(Array)是一个存储相同类型元素的固定长度集合。
你可以理解为:
数组 = 一组同类型变量的集合,通过索引访问。
例如:
csharp
int[] numbers;
访问方式:
csharp
numbers[0]
numbers[1]
numbers[2]
✅ 数组的核心特点
- ✔ 只能存储相同数据类型
- ✔ 长度固定(创建后不能改变)
- ✔ 内存连续存储
- ✔ 索引从 0 开始
- ✔ 数组是引用类型
二、数组的声明与初始化
1️⃣ 声明数组(仅声明,不分配内存)
csharp
int[] nums;
string[] names;
double[] scores;
⚠ 注意:此时数组为 null,还未分配空间。
2️⃣ 使用 new 分配空间
csharp
int[] nums = new int[5];
默认值:
| 类型 | 默认值 |
|---|---|
| int | 0 |
| double | 0.0 |
| bool | false |
| string | null |
3️⃣ 声明时直接赋值
csharp
int[] nums = { 10, 20, 30, 40 };
完整写法:
csharp
int[] nums = new int[] { 10, 20, 30, 40 };
三、数组的访问与遍历
🔥 1️⃣ 使用 for 循环
csharp
int[] scores = new int[5];
for (int i = 0; i < scores.Length; i++)
{
scores[i] = 80 + i * 5;
}
for (int i = 0; i < scores.Length; i++)
{
Console.WriteLine($"索引 {i} 的值为:{scores[i]}");
}
🔥 2️⃣ 使用 foreach
csharp
int[] nums = { 5, 10, 15, 20 };
foreach (int item in nums)
{
Console.WriteLine(item);
}
📌 区别:
for可以获取索引foreach更简洁,但不能直接修改元素
四、数组是引用类型(重点)
数组在 C# 中属于引用类型。
csharp
int[] a = { 1, 2, 3 };
int[] b = a;
b[0] = 999;
Console.WriteLine(a[0]); // 输出 999
说明:
a和b指向同一块内存- 修改
b会影响a
五、数组的内存结构(高分关键)
csharp
int[] arr = new int[3];
内存分配逻辑:
- 变量
arr存储在 栈中 new创建的数组存储在 堆中- 数组元素在堆中连续排列
示意:
id="ax7w37"
栈:
arr → 地址 0x001
堆:
0x001 → [0][0][0]
📌 连续内存的好处:
- 访问速度快
- CPU 缓存友好(提高缓存命中率)
- 时间复杂度 O(1)
六、常见错误(加分项)
❌ 1️⃣ 数组越界
csharp
int[] arr = new int[3];
arr[3] = 10; // IndexOutOfRangeException
原因:
数组索引范围是 0 ~ Length-1,而不是 1 ~ Length。
❌ 2️⃣ 空引用异常
csharp
int[] arr;
arr[0] = 10; // NullReferenceException
原因:
没有使用 new 分配空间,arr 为 null。
七、数组 vs List 对比
| 对比项 | 数组 | List |
|---|---|---|
| 长度 | 固定 | 可动态扩容 |
| 性能 | 更快 | 略慢 |
| 底层 | 连续内存 | 本质也是数组 |
| 使用场景 | 数据量固定 | 数据量变化 |
📌 实际开发中:
- 性能敏感场景 → 优先选择数组
- 业务开发 → 多用 List
八、性能分析(简单专业版)
- 访问元素 → O(1)
- 查找元素 → O(n)
- 插入/删除 → O(n)
- 连续内存 → CPU 缓存友好
这也是数组比链表快的核心原因。
九、面试高频问题
1️⃣ 数组为什么是引用类型?
因为数组对象存储在堆中,变量存储的是地址。
2️⃣ 数组长度可以改变吗?
不能。数组一旦创建,长度不可改变。需要新建数组来进行扩容或修改。
3️⃣ 数组和 List 的底层关系?
List 底层本质是一个数组,当数组容量不够时,会扩容(通常是 2 倍扩容)。
🎯 总结
数组的核心知识点:
- 固定长度
- 引用类型
- 连续内存
- O(1) 访问
- 支持多维数组与交错数组
- 常见异常要注意