.NET Array Dictionary List String 2D Async DataTable Dates DateTime Enum File For Foreach Format IEnumerable If IndexOf Lambda LINQ Parse Path Process Property Regex Replace Sort Split Static StringBuilder Substring Switch Tuple


C#: List

Initialize list. A List can be initialized in many ways. Each element can be added in a loop with the Add method. Alternatively a special initializer syntax form can be used. Objects inside the List can be initialized in this syntax form.

Tip: Most syntax forms are compiled to the same intermediate representation. There is no performance difference.


Example. First, the C# language has many different ways to populate a List with values. But many of them are compiled into the same machine code before runtime. The example below uses the curly brackets and adds elements in these expressions.

Also: You can use an array to initialize a List, or even assign existing elements in a List.

C# program that initializes string list

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
	// Use collection initializer.
	List<string> list1 = new List<string>()
	{
	    "carrot",
	    "fox",
	    "explorer"
	};

	// Use var keyword with collection initializer.
	var list2 = new List<string>()
	{
	    "carrot",
	    "fox",
	    "explorer"
	};

	// Use new array as parameter.
	string[] array = { "carrot", "fox", "explorer" };
	List<string> list3 = new List<string>(array);

	// Use capacity in constructor and assign.
	List<string> list4 = new List<string>(3);
	list4.Add(null); // Add empty references. (BAD)
	list4.Add(null);
	list4.Add(null);
	list4[0] = "carrot"; // Assign those references.
	list4[1] = "fox";
	list4[2] = "explorer";

	// Use Add method for each element.
	List<string> list5 = new List<string>();
	list5.Add("carrot");
	list5.Add("fox");
	list5.Add("explorer");

	// Make sure they all have the same number of elements.
	Console.WriteLine(list1.Count);
	Console.WriteLine(list2.Count);
	Console.WriteLine(list3.Count);
	Console.WriteLine(list4.Count);
	Console.WriteLine(list5.Count);
    }
}

Output

3
3
3
3
3

The first two declarations specify three strings to be added to the List when it is instantiated. The first two statements are equivalent to the final statement using list5, with only a small difference in the intermediate language.

Next: The list3 example copies an external array to the internal buffer of the List at runtime.

And: This avoids unnecessary resizing of the List buffer. The element count is known before any Add methods are executed.

Also, the list4 example is a bad way of initializing a List variable in the normal case. It shows that you can Add any references and then modify the value of those references when initializing your List.

Note: This is useful in nontrivial methods. The example here is poor programming practice.


Object List. You can allocate and assign the properties of objects inline with the List initialization. Object initializers and collection initializers share similar syntax. But they have different purposes.

Object initializer: An object initializer sets the individual fields in the object such as properties.

Collection initializer: A collection initializer sets the elements in the collection, not fields.

Next: This example shows an object that has two properties A and B, and the properties are set in the List initializer.

C# program that initializes object Lists

using System;
using System.Collections.Generic;

class Test // Used in Lists.
{
    public int A { get; set; }
    public string B { get; set; }
}

class Program
{
    static void Main()
    {
	// Initialize list with collection initializer.
	List<Test> list1 = new List<Test>()
	{
	    new Test(){ A = 1, B = "Jessica"},
	    new Test(){ A = 2, B = "Mandy"}
	};

	// Initialize list with new objects.
	List<Test> list2 = new List<Test>();
	list2.Add(new Test() { A = 3, B = "Sarah" });
	list2.Add(new Test() { A = 4, B = "Melanie" });

	// Write number of elements in the lists.
	Console.WriteLine(list1.Count);
	Console.WriteLine(list2.Count);
    }
}

Output

2
2

The example shows how to assign a property in an object instance such as the Test object using the property's name and the equals operator. It uses nested curly brackets "{" and "}".

Property

So: In the initialization of list1, two Test instances are allocated with the specified property values.


Compiler. The C# compiler parses the initializer tokens "{" and "}" and turns them into individual Add method calls on the List. This is true for any List initializer, both those in the first example program and the second example program.

Token

So: The compiler transforms your expression-based declarations into Add method calls. The performance at runtime is equivalent.

List Add

Definite assignment. When examining programs that use collection initializers, you will be surprised to see extra temporary variables being created on the method stack. At runtime, these excess opcodes are eliminated and cause no performance loss.

The C# language specification states that these temporary variables are used to simplify the process of definite assignment analysis. This analysis proves you are always using initialized memory.

Note: See "The C# Programming Language Third Edition, Special Annotated Edition" page 266.


Summary. We looked into some specifics of List initializations. We first saw how to initialize string List collections using the expression-based syntax. We used the copy constructor and Add method. Next we applied object initializers.

Finally: We noted the implementation specifics of List initialization and how it affects definite assignment analysis.

Initialize Array