Использует ли битварный инициализатор типа коллекции его емкость или вам все еще нужно указать его?
То есть:
var list = new List<string>(){ "One", "Two" };
приводят к следующему:
var list = new List<string>(2){ "One", "Two" };
Использует ли битварный инициализатор типа коллекции его емкость или вам все еще нужно указать его?
То есть:
var list = new List<string>(){ "One", "Two" };
приводят к следующему:
var list = new List<string>(2){ "One", "Two" };
Инициализатор объектов просто вызывает Add
для каждого элемента.
var list = new List<string>{ "One", "Two", "Three" };
Как вы можете видеть, в этом случае вызывается конструктор без параметров:
L_0000: nop
L_0001: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor()
L_0006: stloc.1
L_0007: ldloc.1
L_0008: ldstr "One"
L_000d: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
L_0012: nop
L_0013: ldloc.1
L_0014: ldstr "Two"
L_0019: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
L_001e: nop
L_001f: ldloc.1
L_0020: ldstr "Three"
L_0025: callvirt instance void [mscorlib]System.Collections.Generic.List`1<string>::Add(!0)
L_002a: nop
L_002b: ldloc.1
Итак, вы должны установить емкость вручную:
var list = new List<string>(5){ "One", "Two", "Three" };
Скомпилируется в:
L_0000: nop
L_0001: ldc.i4.5
L_0002: newobj instance void [mscorlib]System.Collections.Generic.List`1<string>::.ctor(int32)
// rest is same
Итак, алгоритм довольно очевиден - он вызывает конструктор, который вы указали (без параметров по умолчанию), а затем вызывает Add
для каждого элемента.
ПРИМЕЧАНИЕ. Я знаю, что емкость по умолчанию равна 4 для List<T>
, и я проверил, что произойдет, если мы передадим более 4 элементов в инициализаторе (например, возможно, компилятор определяет, какой конструктор будет вызывать в зависимости от количества элементов), но результат тот же - безразмерный конструктор вызывается по умолчанию.
Я думаю, что назначение инициализаторов коллекции создает небольшие коллекции (1 - 8 элементов), поэтому будет небольшое влияние на производительность (только одно изменение размера, если вы передадите 8 элементов в инициализатор). Никто не ожидает, что вы будете использовать инициализацию на месте с 100 элементами. И если вы собираетесь это сделать, вы должны использовать соответствующий конструктор коллекции.
Инициализатор коллекции использует доступные методы Add
для добавления элементов в коллекцию. Поэтому поведение будет таким же, как использование пустого конструктора с вызовом метода Add
.
Собственно, компилятор изменит синтаксис инициализатора объекта на вызовы методу Add
.
Таким образом, независимо от того, используете ли вы инициализатор объекта, это не имеет значения. Важно то, решите ли вы использовать перегрузку конструктора и количество элементов, которые вы фактически добавляете.
В соответствии с документацией и учитывая, что инициализатор объекта afer имеет счет 2, он также в конечном итоге также установит емкость.
Емкость всегда больше или равна Count
После того, как List инициализируется конструктором без аргументов, внутренний массив устанавливается в массив длиной 0.
Когда Add(), Insert() или InsertRange() называются пропускной способностью списка, пересчитываются:
Если вы укажете емкость, внутренний массив будет создан с таким размером.
Литература: DotNet Источник: RefSrc\Source.NET 4.5\4.5.50709.0\net\ndp\clr\src\BCL\System\Collections\Generic\List.cs\597531\List.cs