C#数组声明即定长、索引从0起、类型强约束,新手常因越界访问和引用语义出错;声明时不可省略new或大括号,int[] arr;为null而非空数组,合法索引范围是0到Length-1。

直接说结论:C#里数组不是“学完就用”,而是“声明即定长、索引从0起、类型强约束”,多数新手栽在越界访问和引用语义上。
怎么声明和初始化数组——别漏掉 new 关键字或大括号
常见错误是写 int[] arr = {1, 2, 3}; 却在方法内试图重新赋值为不同长度的数组,或者误以为 int[] arr; 就等于空数组(它只是 null)。
-
int[] arr1 = new int[3];→ 创建长度为3的int数组,元素默认为0 -
int[] arr2 = {1, 2, 3};→ 等价于new int[] {1, 2, 3},必须带初始化器 -
int[] arr3 = new int[] {1, 2, 3};→ 显式写法,适合类型推导不明确时(如方法参数) - 不能写
int[] arr = new int[3] {1, 2, 3};—— 长度指定和初始化器不能共存
访问数组元素时为什么总抛出 IndexOutOfRangeException?
这不是运行时随机出错,而是每次访问都做边界检查。C# 数组没有负数索引,Length 不是最大索引,而是元素总数。
- 合法索引范围是
0到arr.Length - 1(含) -
arr[arr.Length]必然越界,哪怕你刚用new int[5]创建 - 循环建议用
for (int i = 0; i ,别手滑写成 <code> - 用
foreach (var x in arr)可避免索引操作,但无法修改原数组元素(除非是引用类型且改其内部状态)
string[] 和 int[] 传参时,为什么修改内容有时生效有时不生效?
关键在「数组变量本身是引用类型,但数组里存的是值还是引用」——这决定了你能改什么。
-
int[] nums = {1, 2}; Modify(nums);中,如果Modify写了arr[0] = 99;→ 原数组变化可见(改的是堆上同一块内存) - 但如果
Modify写了arr = new int[]{3, 4};→ 外部nums不受影响(只是把形参指向新地址) -
string[] strs = {"a", "b"};同理:能改strs[0] = "x"(重赋引用),但改strs[0].ToUpper()不影响原值(字符串不可变) - 需要彻底替换数组内容?要么用
ref int[]参数,要么返回新数组
Array.Resize() 真的能“扩容”数组吗?
不能。它只是创建一个新数组,复制旧内容,再把变量指向它——原来的数组会被 GC 回收。性能敏感场景要警惕。
-
Array.Resize(ref arr, 10);是唯一安全用法,必须加ref,否则外部变量仍指向旧数组 - 频繁增删用
List<T>更合适;数组适合长度固定、高性能遍历场景 -
Array.Copy()和Buffer.BlockCopy()效率更高,但后者只支持 blittable 类型(如int,byte),且需注意字节偏移
数组的“简单”是表象,它的不可变长度、零基索引、堆分配特性,会在重构逻辑或对接 API 时突然冒出来——尤其当你把 Array.Empty<T>() 当作默认值,却忘了它不能 Add 的时候。



















