C# IndexOutOfRangeException Fix
In this tutorial, you'll learn about C# IndexOutOfRangeException Fix. We cover key concepts, practical examples, and best practices.
The Problem
Your C# application throws:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at MyApp.Program.Main() in C:\src\Program.cs:line 10
An IndexOutOfRangeException occurs when you access an array, list, or collection with an index that is less than 0 or greater than or equal to the collection's length. Collections are zero-indexed in C#, so valid indices range from 0 to Count - 1.
Quick Fix
Step 1: Check loop bounds
WRONG -- using <= instead of <:
int[] numbers = { 10, 20, 30 };
for (int i = 0; i <= numbers.Length; i++) // i goes to 3, but max index is 2
{
Console.WriteLine(numbers[i]);
}
RIGHT -- use < for zero-indexed collections:
int[] numbers = { 10, 20, 30 };
for (int i = 0; i < numbers.Length; i++)
{
Console.WriteLine(numbers[i]);
}
Or use foreach:
foreach (int num in numbers)
{
Console.WriteLine(num);
}
Step 2: Check for empty collections
WRONG -- accessing first element on an empty list:
var items = new List<string>();
var first = items[0]; // IndexOutOfRangeException
RIGHT -- check if collection has elements:
var items = new List<string>();
if (items.Count > 0)
{
var first = items[0];
}
else
{
Console.WriteLine("Collection is empty");
}
Or use FirstOrDefault():
var first = items.FirstOrDefault(); // returns null if empty
Step 3: Use .Count - 1 for the last element
WRONG -- using .Count instead of .Count - 1:
var last = items[items.Count]; // IndexOutOfRangeException
RIGHT:
if (items.Count > 0)
{
var last = items[items.Count - 1];
}
Or use ^1 (C# 8.0+ index from end):
var last = items[^1]; // last element, but still throws on empty collection
Step 4: Check array slicing (C# 8.0+)
WRONG -- range that exceeds the array:
int[] numbers = { 1, 2, 3 };
var slice = numbers[2..5]; // IndexOutOfRangeException: range extends beyond array
RIGHT -- clamp the range:
int[] numbers = { 1, 2, 3 };
var slice = numbers[2..]; // takes from index 2 to end
// or
var slice = numbers[Math.Min(2, numbers.Length)..Math.Min(5, numbers.Length)];
Step 5: Check multi-dimensional array access
WRONG -- wrong dimension:
int[,] matrix = { { 1, 2 }, { 3, 4 } };
var value = matrix[0, 2]; // second dimension only has indices 0,1
RIGHT -- stay within bounds:
int[,] matrix = { { 1, 2 }, { 3, 4 } };
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.WriteLine(matrix[i, j]);
}
}
Step 6: Use TryGetValue for dictionaries
WRONG -- using indexer directly:
var dict = new Dictionary<string, int> { { "a", 1 } };
var value = dict["b"]; // KeyNotFoundException (not IndexOutOfRange, but similar pattern)
RIGHT -- safe access:
if (dict.TryGetValue("b", out int value))
{
Console.WriteLine(value);
}
Use DodaTech's .NET Analyzer to detect off-by-one errors and suggest safe access patterns for collections.
Prevention
- Use
foreachinstead offorloops when you do not need the index. - Always check
Count > 0before accessing[0]or[^1]. - Use
FirstOrDefault(),LastOrDefault(), andElementAtOrDefault()for safe access. - Use
TryGetValuefor dictionary access. - Use
GetValueOrDefaultforNullable<T>collections.
Common Mistakes with indexoutofrange
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
- Misunderstanding that
Stringis[Char]with poor performance for large text operations - Using
foldlinstead offoldl'causing stack overflow on large lists
These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro