Почему вставка списка терпит неудачу, когда на конструкции предусмотрен достаточный размер?

Если у нас есть следующее объявление переменной:

List<int> list = new List(5);

почему это:

list.insert(2, 3);

сбой со следующей ошибкой:

Index must be within the bounds of the List.

в чем смысл предоставления начального размера?

8 ответов


все начальный размер делает дайте подсказку для реализации, чтобы иметь хотя бы заданную емкость. Он не создает список, заполненный N записи по умолчанию; выделено мной:

инициализирует новый экземпляр List<T> класс пустой и имеет указанную начальную емкость.

если вы продолжите через запись MSDN в раздел Примечания, вы найдете, почему эта перегрузка конструктора при условии (опять же, акцент мой):

емкости List<T> - это количество элементов, которые List<T> можно провести. Как элементы добавляются в List<T>, емкость автоматически увеличена по мере необходимости путем перераспределять внутренний массив.

если размер коллекции можно оценить, указав начальную емкость устраняет необходимость выполнения ряда операций изменения размера при добавлении элементов List<T>.

короче List<T>.Count - это не то же самое как List<T>.Capacity ("если количество превышает емкость при добавлении элементов, емкость увеличивается...").

вы получаете исключение, потому что список только логически содержит элементы, которые вы добавляете, изменение емкости не изменяет количество элементов логически сохраняется. Если бы вы установили List<T>.Capacity меньше List<T>.Count мы можем проверить это поведение будет другим направление:

Unhandled Exception: System.ArgumentOutOfRangeException: capacity was less than
 the current size.
Parameter name: value
   at System.Collections.Generic.List`1.set_Capacity(Int32 value)

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

public static List<T> CreateDefaultList<T>(int entries)
{
    return new List<T>(new T[entries]);
}

размер в конструкторе говорит ему, сколько выделить для фонового массива-он по-прежнему пуст (просто: пустой с определенным количеством начального пространства).

вы можете просто вставить в используемую часть списка или в конце.


внутренне a Список (T) реализуется с помощью массива в фоновом режиме. Когда вы инициализируете список таким образом, вы просто устанавливаете размер базового массива, который изменяется по мере роста списка. Таким образом, вы инициализируете начальную емкость. Это не значит, что в вашем списке так много элементов.

вы добавляете элементы в список, сначала инициализируя его, а затем добавляете элементы в него с помощью .Add(item).


потому что insert предполагает, что список на самом деле имеет, что многие элементы уже вставлены - емкость не то же самое, что размер. Инициализация списка с заданной емкостью просто устанавливает размер внутреннего массива - это оптимизация для предотвращения изменения размера массива, когда вы знаете количество элементов, которые вы собираетесь вставлять.


конструктор List(int) задает начальную емкость списка. В нем не указывается количество исходных элементов. При построении список пуст, поэтому любая вставка может быть выполнена только по индексу 0.


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

когда вы добавляете элементы в список, он сохраняет их в массиве. Когда массив заполнен, он создает новый массив с двойным размером и копирует все элементы. Если у вас есть идея, что вы собираетесь поместить 5000 элементов, вы хотели бы указать эту подсказку, чтобы она не заканчивалась большим изменением размера / копированием массива.

начальный размер делает не однако укажите, что в списке есть какие-либо элементы.


Это потому, что целое число, указанное в конструкторе, является суммой, которую может содержать список. При добавлении элементов список автоматически увеличивается. Изменение размера избегается при указании начальной емкости, соответствующей количеству элементов, которые необходимо добавить.

, вам все равно придется использовать метод Add для добавления новых элементов.

посмотреть раздел замечаний в документации


использовать

listItem.Addrange(number);