一段统计分数的 C# 代码,跑起来就是红字:System.IndexOutOfRangeException,后面跟着「索引超出了数组界限」。盯着看了半天,数组明明赋值了。
问题在循环条件。写成 i <= arr.Length,最后一次 i 正好等于长度,而数组下标最大只到 Length - 1。
for (int i = 0; i <= arr.Length; i++)上面这行改一个字符就好:把 <= 换成 <。差一错误是最常见的越界来源,尤其是从 1 开始编号的业务数据。
报错行不一定是出事的地方
异常信息里带行号,但那个行号指向的是取元素那一下,不是下标算错的地方。所以要往回找,看谁给这个下标赋的值。
异常里的 Actual value 也别放过,它通常写着你越界的那个下标,比如 5,一眼能看出是循环多跑了一次。
多维数组更容易混。arr[i, j] 里两个维度的上界分别是 GetLength(0) - 1 和 GetLength(1) - 1。拿第二维的长度去限第一维,小数据测不出来,数据一多就崩。
几类常见的越界来源
- 业务上从 1 开始编号,直接拿来当下标。
- Split 之后没判断长度就取第二个元素。
- 循环里 Remove 元素,Count 变了,下标没跟着变。
- 接口返回空数组,代码默认至少有一个元素。
还有一种更隐蔽的:数组是接口反序列化来的,字段名对不上,长度是 0,代码却直接取第一个元素。这类问题看日志里的原始响应最快。
数组如果是集合转出来的,注意转换发生在循环前还是循环后。循环中途往里加了元素,长度就对不上了。
怎么让它早点暴露
取之前加一句长度判断,不够就走另一条分支。这比 catch 住异常靠谱,catch 只能兜底,兜完你也不知道丢了几条数据。
调试时把 Length、Count、当前下标一起打印出来,一眼能看出是 0 还是差一。断点打在循环入口,看 i 和 Length 的比值,比单步快。
这类错误九成是边界没算对,跟数组本身没关系。写循环时把 < 和 <= 念一遍,能省很多时间。