Что такое исключение "индекс вне диапазона" и как его исправить?

Я получаю одну из следующих ошибок:

  • "Индекс был вне диапазона. Должен быть неотрицательным и меньше размера коллекции"
  • "Индекс ввода находился за пределами допустимого диапазона. Он должен быть неотрицательным и меньше или равен размеру.
  • "Индекс находился за пределами массива.

Что это значит и как его исправить?

См. также
IndexOutOfRangeException
ArgumentOutOfRangeException

Ответы

Ответ 1

Зачем возникает эта ошибка?

Поскольку вы пытались получить доступ к элементу в коллекции, используйте числовой индекс, который превышает границы коллекции.

Первый элемент в коллекции обычно находится в индексе 0. Последний элемент находится в индексе n-1, где n - это Size коллекции (количество содержащихся в нем элементов). Если вы попытаетесь использовать отрицательное число в качестве индекса или число, превышающее Size-1, вы получите ошибку.

Как работают массивы индексирования

Когда вы объявляете такой массив:

var array = new int[6]

Первый и последний элементы массива

var firstElement = array[0];
var lastElement = array[5];

Итак, когда вы пишете:

var element = array[5];

вы извлекаете шестой элемент в массиве, а не пятый.

Как правило, вы должны перебирать массив таким образом:

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

Это работает, потому что цикл начинается с нуля и заканчивается на Length-1, потому что index уже не меньше Length.

Это, однако, вызовет исключение:

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

Обратите внимание на <=? index теперь будет за пределами диапазона в последней итерации цикла, потому что цикл считает, что Length является допустимым индексом, но это не так.

Как работают другие коллекции

Списки работают одинаково, за исключением того, что вы обычно используете Count вместо Length. Они все равно начинаются с нуля и заканчиваются на Count - 1.

for (int index = 0; i < list.Count; index++)
{
    Console.WriteLine(list[index]);
} 

Однако вы также можете перебирать список с помощью foreach, полностью исключая всю проблему индексирования:

foreach (var element in list)
{
    Console.WriteLine(element.ToString());
}

Вы не можете индексировать элемент, который еще не был добавлен в коллекцию.

var list = new List<string>();
list.Add("Zero");
list.Add("One");
list.Add("Two");
Console.WriteLine(list[3]);  // Throws exception.