← Debugging Guides

阅读中文版本

C# IndexOutOfRangeException / ArgumentOutOfRangeException

Fix index errors by checking collection bounds, using range and index operators safely, and preferring foreach or LINQ over manual indexing.

beginnerdebuggingcsharpexceptionsbounds

Symptoms

  • System.IndexOutOfRangeException: Index was outside the bounds of the array
  • System.ArgumentOutOfRangeException: Index must be within the bounds of the list
  • The error appears only for empty or short collections

Possible causes

  • An array is indexed with a value at or above its Length
  • A List is accessed via the indexer with an invalid index (throws ArgumentOutOfRangeException)
  • A loop bound uses <= Count or Length

Diagnosis steps

Read the exception type to know the collection

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

Interpretation

Array throws IndexOutOfRangeException; List<T> throws ArgumentOutOfRangeException — they narrow the source.

Audit bounds and indices

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

Interpretation

Off-by-one bounds are the most common cause; use i < Count.

Root cause

Arrays and List<T> are zero-indexed and bounds-checked. An index below zero or at/above the element count throws; arrays report IndexOutOfRangeException while List<T> reports ArgumentOutOfRangeException from its indexer.

Fix

Loop with i < Count, use foreach when the index is unnecessary, guard first/last access with a count check, and use range operators (^1, [..]) which are checked and safe.

Risk note

Catching the exception to continue can process incomplete data; fix the index or validate the input instead.

Verify the fix

Rerun with empty and single-element collections and confirm no exception; add tests for the boundary sizes.

Symptoms

This debugging guide addresses “C# IndexOutOfRangeException / ArgumentOutOfRangeException”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.

Observed symptoms include:

  • System.IndexOutOfRangeException: Index was outside the bounds of the array
  • System.ArgumentOutOfRangeException: Index must be within the bounds of the list
  • The error appears only for empty or short collections

Reproduce and Diagnose

Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.

Step 1: Read the exception type to know the collection

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

Array throws IndexOutOfRangeException; List throws ArgumentOutOfRangeException — they narrow the source.

Step 2: Audit bounds and indices

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

Off-by-one bounds are the most common cause; use i < Count.

Likely contributors, in order of frequency:

  • An array is indexed with a value at or above its Length
  • A List is accessed via the indexer with an invalid index (throws ArgumentOutOfRangeException)
  • A loop bound uses <= Count or Length

Root Cause

Arrays and List are zero-indexed and bounds-checked. An index below zero or at/above the element count throws; arrays report IndexOutOfRangeException while List reports ArgumentOutOfRangeException from its indexer.

The Fix

Loop with i < Count, use foreach when the index is unnecessary, guard first/last access with a count check, and use range operators (^1, [..]) which are checked and safe.

Watch out: Catching the exception to continue can process incomplete data; fix the index or validate the input instead.

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>();

Verify and Prevent

Rerun with empty and single-element collections and confirm no exception; add tests for the boundary sizes.

Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.

This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.