Does using the braced initializer on a collection type set it's capacity or do you still need to specify it?
That is, does:
var list = new List<string>(){ "One", "Two" };
result in the same as this:
var list = new List<string>(2){ "One", "Two" };
Object initializer simply calls Add
for each item.
var list = new List<string>{ "One", "Two", "Three" };
As you can see, in this case parameterless constructor is called:
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
So, you should set capacity manually:
var list = new List<string>(5){ "One", "Two", "Three" };
Compiles into:
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
So, algorithm is pretty obvious - it calls constructor which you specified (parameterless by default) and then calls Add
for each item.
NOTE: I know, that default capacity is 4 for List<T>
and I verified what happens if we pass more than 4 items in initializer (e.g. maybe compiler determines which constructor to call depending on items count) but result is same - parameterless constructor is called by default.
I think purpose of collection initializers is creating small collections (1 - 8 items), thus there will be a little performance impact (only one resize if you will pass 8 items into initializer). Nobody expects you will use in-place initialization with 100 items. And if you are going to do that, you should use appropriate constructor of collection.
The collection initializer uses the available Add
methods to add the items to the collection. Therefore the behaviour would be the same as using an empty constructor with calling the Add
method.
Actually, the compiler will change your object initializer syntax to calls to the Add
method.
So, whether you use the object initializer is irrelevant. What matters is whether you decide to use the constructor overload and the amount of items you actually add.
After List is initialised with the no-argument constructor, the internal array is set to an array of length 0.
When Add(), Insert() or InsertRange() are called the capacity of the list is recalculated:
- If there are no other elements in the list, the capacity is set to 4
(the default capacity).
- If there ARE other elements, the capacity is
set to twice the number of elements.
If you specify the capacity, the internal array is created at that size.
References:
DotNet Source: RefSrc\Source.NET 4.5\4.5.50709.0\net\ndp\clr\src\BCL\System\Collections\Generic\List.cs\597531\List.cs
According to the documentation and considering that afer object initializer a count is 2, it will eventually set capacity too.
Capacity is always greater than or equal to Count