Ответ
Capacity — это свойство класса List<T>, которое определяет общее количество элементов, которое внутренний массив списка может вместить без перераспределения памяти. Фактическое количество элементов в списке определяется свойством Count.
Как это работает:
При создании списка выделяется внутренний массив. Когда вы добавляете элементы (Add) и Count достигает значения Capacity, происходит автоматическое увеличение емкости (обычно в 2 раза), что влечет за собой:
- Выделение нового, большего массива.
- Копирование всех существующих элементов из старого массива в новый.
- Продолжение работы с новым массивом.
Пример:
// Создаем список с начальной Capacity = 4
List<int> numbers = new List<int>(4);
Console.WriteLine(numbers.Capacity); // 4
numbers.Add(1); // Count = 1, Capacity = 4
numbers.AddRange(new[] { 2, 3, 4 }); // Count = 4, Capacity = 4
numbers.Add(5); // Count = 5, Capacity увеличивается до 8
Console.WriteLine(numbers.Capacity); // 8
Зачем это нужно и best practices:
- Производительность: Перераспределение массива — дорогая операция. Если вы заранее знаете примерное количество элементов, указание начальной
Capacityв конструкторе позволяет избежать множественных переаллокаций. - Соотношение Capacity и Count:
Capacityвсегда >=Count. Присвоение значенияCapacityменьшего, чем текущийCount, выброситArgumentOutOfRangeException. - Оптимизация памяти: Если после массового удаления элементов
Capacityзначительно превышаетCount, можно вызвать методTrimExcess(), чтобы уменьшитьCapacityближе кCount(реализация не гарантирует точного равенства). - Прямое управление: Свойство
Capacityимеет сеттер, но его использование требует осторожности.
Ответ 18+ 🔞
Давай разберём эту штуку про Capacity в List<T>, чтобы было понятно, как муха с котлетой.
Представь, что List<int> — это такой прожорливый чемодан на колёсиках. Так вот:
Count— это сколько носков и трусов ты в него уже напихал.Capacity— это на сколько пар носков этот чемодан вообще рассчитан, пока у него молния не начнёт трещать по швам.
Как оно живёт:
Создаёшь ты пустой список — ему выделяют внутри массив-кармашек, скажем, на 4 элемента. Пока ты кидаешь туда свои циферки (Add), Count растёт, а Capacity спокойно курит в сторонке. Но в один прекрасный момент ты пытаешься запихнуть пятый элемент, а места-то уже нет, блядь!
Тогда список, недолго думая, делает вот что: берет новый чемодан (массив) в два раза больше, перекладывает все старые вещи (элементы) аккуратненько на свои места, а старый чемодан выкидывает на помойку (отдаёт сборщику мусора). И так каждый раз, когда ему становится тесно. Операция, конечно, не из быстрых — представь, как ты каждый раз перепаковываешь весь багаж.
Смотри, как это выглядит в коде:
// Делаем чемодан, который изначально рассчитан на 4 пары носков (Capacity = 4)
List<int> numbers = new List<int>(4);
Console.WriteLine(numbers.Capacity); // 4 — вот его заводская вместимость
numbers.Add(1); // Кинул один носок. Count = 1, Capacity = 4 (ещё овердохуя места)
numbers.AddRange(new[] { 2, 3, 4 }); // Докинул ещё три. Count = 4, Capacity = 4 (чемодан полон!)
numbers.Add(5); // А вот пытаешься запихнуть пятый... Ёпта! Места нет!
// *звуки перепаковки багажа*
// Count = 5, Capacity теперь увеличен до 8
Console.WriteLine(numbers.Capacity); // 8 — вот новый, просторный чемодан!
Зачем это всё надо и как не выстрелить себе в ногу:
-
Производительность, ёб твою мать! Если ты заранее знаешь, что у тебя будет, ну, тысяч 100 записей, то сразу укажи это в конструкторе:
new List<int>(100_000). Чемодан сразу сделают здоровенным, и он не будет каждые 5 секунд перепаковываться. Экономия — реальная. -
Capacity всегда >= Count. Это как аксиома. Нельзя сделать чемодан меньше, чем вещей в нём уже лежит. Попробуешь — получишь
ArgumentOutOfRangeExceptionпрямо в ебальник. -
Жрать меньше памяти. Допустим, ты был максималистом, сделал
Capacityна миллион, а потом 999990 элементов удалил. Получился полупустой чемодан размером с хоккейную коробку. Чтобы не выглядеть идиотом, можно вызватьTrimExcess(). Он попробует ужать внутренний массив поближе к реальномуCount. Ключевое слово — попробует, гарантий тебе никаких. -
Ручное управление. У
Capacityесть сеттер. Менять его можно, но осторожно, как матан в универе. Если поставишь значение меньшеCount— см. пункт 2, будет больно. Если больше — просто выделится новый массив и всё переедет. Обычно в этом нет смысла, лучше сразу в конструкторе указать.
Короче, Capacity — это про то, чтобы твой список не дрочился с постоянным перевыделением памяти, когда ты этого не ожидаешь. Предусмотрительность рулит.