Start learning free

LESSON 95 OF 347 · ARRAYS I

Exceeding Static Array Bounds in C#: IndexOutOfRangeException

Lesson Read the full explanation

When accessing array data with indices, the most common problem we can run into is exceeding the array's bounds.

Remember, the items of an array are indexed from 0 to length - 1. Any index which is not in this range is invalid.

When you try to access an item with an invalid index, C# raises an exception:

int[] ourArray = {50, 40, 30};

// Valid indices: 0, 1, 2
Console.WriteLine(myArray[0]); // Output: 50
Console.WriteLine(myArray[2]); // Output: 30

// Invalid indices: 3, 30, -1
Console.WriteLine(myArray[3]); // raises IndexOutOfBounds exception
Console.WriteLine(myArray[30]); // raises IndexOutOfBounds exception
Console.WriteLine(myArray[-1])); // raises IndexOutOfBounds exception

As programmers, we always want to make sure that we don't exceed one array's bounds in our programs.


Assignment
Follow the Coding Tutorial and let's play with some arrays.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 1
    Ctrl + Enter to check

    C# · ARRAYS I

    Exceeding Static Array Bounds in C#, explained

    The valid range

    An array with Length elements has the valid indexes 0 through Length - 1. Any other index is outside the array's bounds. The compiler can't generally know the value of an index, so the code compiles, but the program checks the index each time it runs and throws an IndexOutOfRangeException if it is invalid.

    int[] ourArray = {50, 40, 30};
    
    // Valid indexes: 0, 1, 2
    Console.WriteLine(ourArray[0]);  // 50
    Console.WriteLine(ourArray[2]);  // 30
    
    // Invalid indexes: 3 and above, and anything negative
    Console.WriteLine(ourArray[3]);  // throws IndexOutOfRangeException
    

    The message reads Index was outside the bounds of the array. A negative index such as -1 fails the same way. Unlike Python, C# does not count negative indexes from the end. To read from the end, use Length - 1 or the ^1 syntax.

    When the exception isn't caught, the program stops at that line, so the lines after it never run. That is why this error is worth avoiding rather than handling: it almost always points to an off-by-one mistake.

    The exercise, step by step

    The starter code is meant to print the last element of ages, but it throws:

    int[] ages = {14, 32, 50, 21};
    
    Console.WriteLine(ages[ages.Length]);
    
    1. Find the index. ages.Length is 4. The array's indexes are 0, 1, 2 and 3, so index 4 is one past the end.
    2. Move one step back. The last element is at Length - 1, which is 3. Changing the index to ages.Length - 1 reads the value 21.

    The fixed program:

    int[] ages = {14, 32, 50, 21};
    
    Console.WriteLine(ages[ages.Length - 1]);
    

    It prints:

    21
    

    Guarding against the error

    You can check the index before using it. The check has two parts, because both ends of the range matter:

    int[] ages = {14, 32, 50, 21};
    int index = 4;
    
    if (index >= 0 && index < ages.Length) {
        Console.WriteLine(ages[index]);
    } else {
        Console.WriteLine("No such position");
    }
    

    This prints No such position. You could also catch the exception with try and catch (IndexOutOfRangeException), but a plain check is simpler and shows your intent. Catching is better saved for failures you can't test for in advance.

    In a test or while debugging, read the exception text first. It names the exception type, and the stack trace points to the line number that used the bad index. Then work out which index you passed and compare it with the array's length.

    Because the check happens at run time, a program can work for months and fail the first time it receives an unusual input, such as an empty array. Testing small and empty inputs is therefore the best way to find these bugs early.

    Common causes

    • Using the length as an index. This is the bug above and the most frequent one. The length is a count; the last index is one less.
    • Loops that go one step too far. A loop condition of i <= array.Length reaches the invalid index. Use i < array.Length.
    • Empty arrays. For an array of length 0, even index 0 is invalid, and array[array.Length - 1] asks for index -1.
    • Indexes computed from input. When an index comes from a calculation or from the user, check index >= 0 && index < array.Length before using it.

    Why C# checks bounds

    Some languages let a program read past the end of an array and silently return whatever happens to be in memory. C# never does that. Every array access is checked, so a mistake produces a clear exception with a line number, not wrong results that appear much later. The check is the reason the error message exists in the first place.

    Things to try

    Try these on a four-element array to see which ones throw. The index 0 works, the index 3 works, and the indexes 4 and -1 throw. Then try ages[ages.Length - 1] on an array created with new int[0] and watch it fail at index -1.

    Key takeaways

    • Valid array indexes run from 0 to Length - 1.
    • An invalid index throws IndexOutOfRangeException at run time, not at compile time.
    • To get the last element, use array[array.Length - 1].
    Keep going with C#About 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free