Tim
Tim

Reputation: 5653

Does using the braced initializer on collection types set the initial capacity?

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" };

Upvotes: 19

Views: 793

Answers (4)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236248

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.

Upvotes: 16

Uatec
Uatec

Reputation: 141

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

Upvotes: 1

Myrtle
Myrtle

Reputation: 5831

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.

Upvotes: 3

Tigran
Tigran

Reputation: 62266

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

Upvotes: 0

Related Questions