Емкость списка по умолчанию

Какова емкость списка по умолчанию?

8 ответов

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

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

List<int> list = new List<int>();
int capacity = list.Capacity;
Console.WriteLine("Capacity: " + capacity);

for (int i = 0; i < 100000; i++)
{
    list.Add(i);
    if (list.Capacity > capacity)
    {
        capacity = list.Capacity;
        Console.WriteLine("Capacity: " + capacity);
    }
}

Почему бы тебе просто не попробовать?

Console.WriteLine("Default capacity of a List: " + new List<int>().Capacity);

Этот ответ будет работать на всех версиях.NET, имеющих список. На моей версии это бывает 0.

В соответствии с примером в документации MSDN без параметров конструктор, начальная емкость списка создается с:

List<string> x = new List<string>();

равно 0. Насколько я могу судить, это не задокументировано как гарантия и не задокументирована политика изменения размера (т. е. в настоящее время она может удваиваться с минимумом 4, но в.NET 5.0 она может утроиться с минимумом 128.) Вы не должны полагаться на это поведение, в основном.

Емкость списка по умолчанию составляет 4 элемента (после вставки исходного элемента, в противном случае он имеет размер 0)

var list = new List<int>();
list.Add(1);

Assert.AreEqual(4, list.Capacity);

По умолчанию емкость равна 0, но если вы создадите пустой список [ List1 ], как показано ниже. Если в созданном вами списке есть элементы в [ List2 ], как показано ниже, количество добавляемых вами элементов становится больше N, чем 2. Объем по умолчанию варьируется.

List<int> List1 = new List<int>(); //count=0, capacity=0
List<int> List2 = new List<int>(){ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; //count=11, capacity=16

При добавлении элементов типа Array разработчики расширили массив с помощью метода ReSize. Работало очень медленно. При разработке типа List емкость была в некоторой степени увеличена. Это соотношение рассчитано как N выше 2.

Если в список добавляется больше, чем количество членов, текущая емкость удваивается. Емкость не уменьшится, если вы удалите некоторые значения из списка. Емкость только увеличивается, а не уменьшается. Даже метод Clear на это не влияет.

Емкость следует использовать, если вы примерно знаете, сколько предметов вы хотите сохранить в Списке (или в Стеке, или в Очереди).

В этом случае вы избежите копирования памяти. Копирование памяти происходит из-за того, что под капотом списки (стеки и очереди) полагаются на массив для хранения своих элементов. Этот размер массива соответствует вашей емкости, но он не совпадает с размером списка. Поскольку размер списка должен быть больше размера массива, реализация List будет выделять больший массив (в 2 раза, а может быть и меньше) и будет копировать все элементы из старого массива в новый плюс новые добавленные элементы.

Итак, если вы знаете, что в вашем списке может быть, скажем, от 50 до 60 элементов, создайте список с емкостью 60, и никакого освобождения памяти не произойдет.

Примечание: похоже, сборщику мусора не придется очищать старые массивы.

Все это находится в одной строке, чтобы обеспечить способность хранить другой элемент:

int num = this._items.Length == 0 ? 4 : this._items.Length * 2;

Получил это из mscorlib 4.0.0.0 в разобранном виде - конечно, как сказал Джон, нельзя гарантировать, что это не изменится в будущем (пока оно все еще остается на 0, 4, 8, 16...).

Конечно, вы можете установить его самостоятельно, так что это может быть 3, 9, 27 и т. Д.

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

      List<string> dinosaurs = new List<string>();
Console.WriteLine("\nInit:\nCapacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);

dinosaurs.Add("Deinonychus");
Console.WriteLine();
foreach (string dinosaur in dinosaurs)
{
    Console.WriteLine(dinosaur);
}
Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);

dinosaurs.Add("Mamenchisaurus");
dinosaurs.Add("Amargasaurus");
dinosaurs.Add("Compsognathus");
dinosaurs.Add("Son of Compsognathus");
Console.WriteLine();
foreach (string dinosaur in dinosaurs)
{
    Console.WriteLine(dinosaur);
}
Console.WriteLine("Capacity: {0}", dinosaurs.Capacity);
Console.WriteLine("Count: {0}", dinosaurs.Count);

/* In C# 11 This code example produces the following output:

Init:
Capacity: 0
Count: 0

Deinonychus
Capacity: 4
Count: 1

Deinonychus
Mamenchisaurus
Amargasaurus
Compsognathus
Son of Compsognathus
Capacity: 8
Count: 5

==>> default: 0
*/

Другие вопросы по тегам