Start learning free

LESSON 59 OF 347 · STRINGS I

Exceeding String Bounds in C#: IndexOutOfRangeException

Lesson Read the full explanation

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

Remember, the characters of a string are normally indexed from 0 to length - 1.

Any index which is strictly greater than length - 1 is invalid.

When you try to access a character with an invalid index, C# throws a StringIndexOutOfBoundsException:

string car = "ford";

// Valid indices: 0, 1, 2, 3
Console.WriteLine(car[0)); // Output: f
Console.WriteLine(car[3)); // Output: d

// Invalid indices: 4, 30
Console.WriteLine(car[4)); // StringIndexOutOfBoundsException
Console.WriteLine(car[30)); // StringIndexOutOfBoundsException

This code would throw a StringIndexOutOfBoundsException: string index out of range: 4

In conclusion, we always want to double check our code to make sure that we don't exceed one string's bounds in our programs.


Assignment
Follow the Coding Tutorial and let's practice with string bounds!


Hint
Look at the examples above if you get stuck.


STEP 1 OF 1
    Ctrl + Enter to check

    C# · STRINGS I

    Exceeding String Bounds in C#, explained

    What goes wrong

    The characters of a string have indexes from 0 to Length - 1. Any index outside that range is invalid, and using one throws an IndexOutOfRangeException at run time. The compiler can't catch it, because the index is usually only known when the program runs.

    string car = "ford";
    
    Console.WriteLine(car[0]);   // f
    Console.WriteLine(car[3]);   // d
    
    Console.WriteLine(car[4]);   // IndexOutOfRangeException
    

    The string has 4 characters, so the valid indexes are 0, 1, 2 and 3. Index 4 is one position past the end. An index such as 30 fails the same way, and so does a negative one like car[-1].

    The exception's message says that the index was outside the bounds of the array, even though a string is not an array. The program stops at that line unless the exception is caught, so no later statements run.

    Why it is so common

    Most out-of-range errors come from one idea: confusing a count with a position. Length is how many characters there are, and the last position is one less than that. Writing car[car.Length] is the classic off-by-one error.

    Two other situations cause it often:

    • Empty strings. "" has no valid index at all, so even ""[0] throws.
    • Loops that run too far. A loop written as i <= s.Length reaches an index that doesn't exist on its last pass. The correct condition is i < s.Length.

    Tracing a loop bug

    Here is a loop that looks right but goes one step too far:

    string car = "ford";
    
    for (int i = 0; i <= car.Length; i++) {
        Console.WriteLine(car[i]);
    }
    

    It prints f, o, r and d, and then the loop tries i = 4. The condition 4 <= 4 is true, so the body runs with car[4] and throws. Changing <= to < stops the loop after index 3.

    When you hit this exception, find the index expression on the failing line and work out its value for the string involved. Compare it to the range 0 to Length - 1. That usually shows the problem straight away.

    Guarding against it

    Check the index before you use it:

    string car = "ford";
    int i = 4;
    
    if (i >= 0 && i < car.Length) {
        Console.WriteLine(car[i]);
    } else {
        Console.WriteLine("Index " + i + " is out of range");
    }
    

    This prints Index 4 is out of range. For the last character, compute the index from the length and make sure the string is not empty first.

    Catching the exception

    You can also catch the exception with try and catch so the program continues:

    string car = "ford";
    
    try {
        Console.WriteLine(car[4]);
    } catch (IndexOutOfRangeException) {
        Console.WriteLine("That index does not exist");
    }
    

    This prints That index does not exist. Catching is a safety net, though. For a plain index check, testing the index first is simpler and says more clearly what the code expects.

    A related exception

    Indexing with [] throws IndexOutOfRangeException, but Substring reports a bad request with a different type, ArgumentOutOfRangeException. Code written for other languages may expect different exception names, so match the one C# actually throws when you catch errors.

    string car = "ford";
    
    Console.WriteLine(car.Substring(2, 2));  // rd
    Console.WriteLine(car.Substring(2, 5));  // ArgumentOutOfRangeException
    

    The second call fails because only two characters remain after index 2, and the call asks for five. The idea is the same as with indexing: the request has to stay inside the string.

    The exercise, step by step

    The lesson starts with message = "I love pancakes" and a line that is meant to print the last character, s. Instead the program stops with an IndexOutOfRangeException.

    1. Count the characters. The string has 15 characters, so message.Length is 15 and the valid indexes are 0 to 14.
    2. Spot the bad index. The starter code indexes with message.Length, which is 15, one past the end.
    3. Subtract one. The last character is at message.Length - 1, which is 14.
    string message = "I love pancakes";
    
    Console.WriteLine(message[message.Length - 1]);
    

    The program now prints s.

    Key takeaways

    • Valid indexes are 0 to Length - 1; anything else throws IndexOutOfRangeException.
    • s[s.Length] is always one too far.
    • An empty string has no valid index.
    • Loops over a string should use i < s.Length, not <=.
    • When an index might be invalid, check it before using it.
    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