Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

collections

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" };
like image 208
Tim Avatar asked Sep 24 '13 07:09

Tim


People also ask

How to use collection initializer in C#?

Collection initializers let you specify one or more element initializers when you initialize a collection type that implements IEnumerable and has Add with the appropriate signature as an instance method or an extension method. The element initializers can be a simple value, an expression, or an object initializer.

What is initializing in C#?

Initialization sets the variable to a new instance. It must be to a type that is compatible with the declaration type. 1static void Main(string[] args) 2{ 3 string a = "Hello World"; 4 Console.

What is initializer in VB net?

Object initializers enable you to declare and instantiate an instance of a class in a single statement. In addition, you can initialize one or more members of the instance at the same time, without invoking a parameterized constructor.


1 Answers

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.

like image 142
Sergey Berezovskiy Avatar answered Oct 19 '22 22:10

Sergey Berezovskiy