← Назад к вопросам

Что такое Capacity у списка?

2.0 Middle🔥 121 комментариев
#Основы C# и .NET

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое Capacity у списка в C#?

В контексте языка C# и коллекции List<T>, Capacity (ёмкость) — это внутреннее свойство, которое определяет текущий размер внутреннего массива, используемого для хранения элементов списка. Это количество элементов, которое List<T> может содержать без выделения дополнительной памяти (без увеличения размера внутреннего массива). Capacity напрямую связано с механизмом управления памятью и производительностью списка.

Внутреннее устройство List<T> и роль Capacity

  1. Внутренний массив: List<T> внутри использует обычный массив T[] для хранения своих элементов. Именно этот массив и имеет размер, равный Capacity.
  2. Размер списка vs. Ёмкость: Важно различать:
    • Count — текущее количество элементов, фактически добавленных в список (логический размер).
    • Capacity — физический размер внутреннего массива (ёмкость).
List<int> numbers = new List<int>();
Console.WriteLine($"Count: {numbers.Count}, Capacity: {numbers.Capacity}"); // Count: 0, Capacity: 0

numbers.Add(1);
Console.WriteLine($"Count: {numbers.Count}, Capacity: {numbers.Capacity}"); // Count: 1, Capacity: 4

Как Capacity изменяется динамически

При добавлении элементов, если Count достигает значения Capacity, происходит автоматическое увеличение Capacity (reallocation):

  1. Создаётся новый внутренний массив большего размера.
  2. Все существующие элементы копируются в новый массив.
  3. Старый массив становится доступным для сборщика мусора (GC).
List<string> items = new List<string>(2); // Явно задаём начальную Capacity = 2
items.Add("A");
items.Add("B"); // Count = 2, Capacity = 2
items.Add("C"); // Происходит увеличение Capacity! Count = 3, Capacity становится 4

Стратегия увеличения Capacity

По умолчанию, при исчерпании Capacity, ёмкость удваивается (начиная с минимального значения 4, если список создан без указания Capacity):

  • Начало: Capacity = 0 (при пустом конструкторе).
  • Первое добавление: Capacity становится 4.
  • Далее: 4 → 8 → 16 → 32 → ... (при каждом исчерпании).
  • Это сделано для снижения частоты дорогостоящих перераспределений памяти, но может привести к избыточному расходу памяти.

Управление Capacity

Разработчик может явно управлять Capacity для оптимизации:

  1. Задание начальной Capacity в конструкторе:

    // Если известно приблизительное количество элементов
    List<int> list = new List<int>(1000); // Capacity сразу = 1000
    
  2. Использование свойства Capacity:

    list.Capacity = 200; // Можно увеличить (если значение >= Count)
    list.TrimExcess();   // Устанавливает Capacity = Count (но это рекомендация, а не гарантия)
    

Практическое значение Capacity

  • Производительность: Частое увеличение Capacity ведёт к дополнительным аллокациям памяти и копированию данных, что снижает производительность, особенно при работе с большими списками.
  • Память: Слишком большая Capacity приводит к неэффективному использованию памяти (лишние незаполненные ячейки массива).
  • Оптимизация: В сценариях, когда известно максимальное количество элементов, задание Capacity заранее исключает перераспределения.

Пример: влияние Capacity на производительность

// Медленно: много перераспределений
var slowList = new List<int>();
for (int i = 0; i < 100000; i++) slowList.Add(i); // Capacity меняется много раз

// Быстро: одно перераспределение (если изначально задана достаточная Capacity)
var fastList = new List<int>(100000);
for (int i = 0; i < 100000; i++) fastList.Add(i); // Capacity не меняется

Важные нюансы

  • Минимальные значения: При создании пустого списка Capacity = 0. При первом добавлении элемента он становится 4 (если не задан иначе).
  • Ограничения: Capacity не может быть установлена меньше текущего Count — будет выброшено ArgumentOutOfRangeException.
  • Сброс Capacity: Метод Clear() очищает список (Count = 0), но не сбрасывает Capacity — внутренний массив остаётся прежнего размера. Это позволяет эффективно повторно использовать список.

Заключение

Capacity — это важный аспект внутренней оптимизации List<T>, балансирующий между производительностью (минимизация перераспределений) и эффективным использованием памяти. Понимание механизма Capacity позволяет писать более эффективный код, особенно в высоконагруженных приложениях, где частые аллокации памяти могут стать узким местом. Разумное управление Capacity (например, задание начального размера при известном количестве элементов) — признак опытного C#-разработчика.