Comments 14
1)Про какую версию net вы пишите? Просто раньше точно было увеличение размера массива в два раза, что собственно снижало производительность из-за нагрузки на память. Сейчас же я вижу +1 к предыдущему размеру,возник вопрос. 2) вы написали, что List<t> будет быстрее ArrayList. Не всегда. Основное преимущество дженерик типов, как вы и написали, уход от упаковки объектов. Но если у нас ссылочные объекты, то их и упаковывать не надо. Вывод: дженерик будет быстрее, только для значимых типов. Для ссылочные типов может быть почти одинаковой, если задать правильную емкость. Пожалуйста, поправьте в статье.
По поводу +1 внимательно почитайте код метода Grow: значение аргумента используется при необходимости для коррекции после попытки удвоения размера.
1) Посмотрите внимательно код Grow. Увеличивается в 2 раза, и проверяется, что новое capacity удовлетворено.
1) Актуальный на сегодняшнее время .NET 6.0.9. Как вам уже ответили ранее, размер увеличивается в два раза. В статье написано про это в описании алгоритма работы метода Grow:
если внутренний массив пуст, то ёмкость списка будет равна 4, иначе удвоенной длине массива
2) Я согласен, что наибольший выигрыш будет при использовании значимых типов, в этом и суть. А про разницу для ссылочных типов есть в статье:
Разница при использовании ссылочных типов несущественная, так как нет операций упаковки и распаковки, которые являются очень тяжёлыми.
Продолжая обсуждение роста размера: известно, что рост x2 это очень неудачный выбор точки зрения фрагментирования памяти. Разработчики .NET скорее всего в курсе этого, и даже интересно, почему тогда не исправлено?..
В дотнете управляемая память освобождается только сборщиком мусора и никак иначе. А если он оказался запущен — он заодно и дефрагментацию кучи проведёт.
Поэтому фрагментация памяти — вообще не та проблема о которой следует думать в .NET
А потому думать о фрагментации в .NET может все-таки оказаться полезным, но перед тем, как думать, желательно все же померить, что там происходит в реале.
PS На всякий случай уточню: информация о работе сборщика мусора взята из книги Кокосы, 2018 года издания. Совет померить — тоже.
метод OrderBy производит устойчивую сортировку, а Sort – нет.
Раз уж вы, как я понял, заглядывали в исходный код, то было бы неплохо указать, какой метод сортировки реально использует Sort. Иногда это знать полезно: например (вспоминаю теорию), с Quick Sort можно, если не повезет, нарваться на O(N2), а Heap Sort хоть и в среднем медленнее, но дает гарантию, что на квадратичную сложность не нарвешься с любыми данными.
Да, вы правы, можно было бы написать про это. Про используемые алгоритмы сортировки есть на MSDN:
This method uses Array.Sort, which applies the introspective sort as follows:
1) If the partition size is less than or equal to 16 elements, it uses an insertion sort algorithm;
2) If the number of partitions exceeds 2 log n, where n is the range of the input array, it uses a Heapsort algorithm;
3) Otherwise, it uses a Quicksort algorithm.
....
This method is an O(n log n) operation, where n is Count.
Про выделение памяти полезно ещё в Diagnostic Tools глянуть на выходе из метода.
static void Main()
{
var count = 1000000;
var collection = new ArrayList(count);
for (var i = 0; i < count; i++)
collection.Add(i);
}
Выше приведенный код даст помимо ArrayList
миллион упакованных Int32
.

ArrayList
здесь ссылается на Object[]
, который ссылается на Int32
.

Использование List<int>
дает другую картину.
static void Main()
{
var count = 1000000;
var collection = new List<int>(count);
for (var i = 0; i < count; i++)
collection.Add(i);
}

Никаких упакованных Int32
. List<Int32>
ссылается на Int32[]
. Использование памяти значительно сокращено.
Особенности реализации List в C#