← 中文资源

简体中文版本

C# 索引越界异常 / 参数越界异常

通过检查集合边界、安全使用范围与索引运算符,并优先用 foreach 或 LINQ 替代手动索引,修复索引类异常。

阅读英文原文

症状

本篇指南处理“C# IndexOutOfRangeException / ArgumentOutOfRangeException”。请从症状出发,按顺序执行诊断,在推进前确认每个假设;随后通过修复与验证步骤闭环。

可观察到的症状包括:

  • System.IndexOutOfRangeException: Index was outside the bounds of the array
  • System.ArgumentOutOfRangeException: Index must be within the bounds of the list
  • 仅在空或较短集合时出现错误

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

dotnet run 2>&1 | grep -E "IndexOutOfRange|ArgumentOutOfRange"

数组抛 IndexOutOfRangeException;List 抛 ArgumentOutOfRangeException,据此可缩小来源。

步骤 2

grep -rn "<=" Program.cs | grep -i "length\|count"

差一的上界最常见;应使用 i < Count。

常见诱因(按出现频率排序):

  • 用大于等于 Length 的值索引数组
  • 用非法索引访问 List(抛 ArgumentOutOfRangeException)
  • 循环上界用了 <= Count 或 Length

根因

数组与 List 从 0 开始索引并做边界检查。索引小于零或大于等于元素数即抛异常;数组报 IndexOutOfRangeException,而 List 的索引器报 ArgumentOutOfRangeException。

修复

循环用 i < Count,无需索引时用 foreach,访问首/末元素前检查数量,并使用范围运算符(^1、[..]),它们经过检查且安全。

注意:捕获异常后继续可能处理不完整数据;应修正索引或校验输入。

int[] values = GetValues();

for (int i = 0; i < values.Length; i++)
{
    Console.WriteLine(values[i]);
}

// LINQ / foreach avoid manual indexing entirely
foreach (var v in values) Console.WriteLine(v);

// safe first element
if (values.Length > 0) Console.WriteLine(values[0]);

// range operators are bounds-checked
var tail = values.Length > 0 ? values[1..] : Array.Empty<int>();

验证

用空集合与单元素集合重跑并确认无异常;为边界大小补充测试。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。