C# Advanced

C# List

The objective of this article is to familiarize you with the generic C# List, which is implemented via List<T> collection class. You will learn how to declare, create, instantiate and use this type of collection, including code examples of the commonly used methods and properties of List<> class. Finally, different ways to iterate through all the items of the collection.

Table of Contents

What Is the List in C#?

The generic List<T> class is the simplest of the collection classes defined by the .NET Framework. The first thing to understand is that the C# List is a simple ordered list of items that has the ability to store any type of object, just like an array. Also, like an array, you must specify which type of object you want a particular List to store. This means that if you want a List of integers of the int data type then you can create a List that will store only the int type.

For resizable lists, .NET offers the generic class List<T>. This class implements the IList, ICollection, IEnumerable, IList<T>, ICollection<T>, and IEnumerable<T> interfaces.


Properties and Methods of C# List Class

C# List class provides several methods for manipulating the items it contains. The following is list of some frequently used properties and methods defined in a List<T>.

C# List

You can declare and initialize C# List as in the following code.

using Statement

To work with the C# List, you need to add the following namespace at the beginning your code:

using System.Collections.Generic;

How Do You Create a List in C#?

You can create C# List using either one or two statements.

Declare and Initialize C# List Using Two Statements

The T part of the declaration indicates that the class will work with a certain type. After you finish the declaration, the class knows what data type it will manipulate, and it can behave as if it were designed with that data type in mind.

List<T> listName; // declaration

Instead of assigning items in the declaration, you use new keyword with default constructor to initialize an empty List to be stored temporarily in the listName variable. This is how you create an object from the List<> class for a given data type:

listName = new List<T>(); // initialization

The default capacity of a list is 0 items, but you can assign a different capacity to create a list. When the number of items in a list exceeds capacity, the list is resized to allow more items. With every resize the capacity is automatically doubled.

listName = new List<T>(capacity);
// OR
listName.Capacity = number;

The capacity can be decreased by calling TrimExcess method or by setting the Capacity property explicitly.

Declare and Initialize C# List on a Single Line

Declaration and initialization of a list at the same time on a single line.

List<T> listName = new List<T>(); // declaration & initialization

Use of var keyword with a list to declare a variable that infers its type from the value that’s assigned to it.

var listName = new List<T>();

C# Collection Initializers

You can assign values to collections using collection initializer syntax introduced in C# 3.0. It is a shortened syntax to create an instance of a collection. With a collection initializer, the values can be assigned all at once during the declaration using curly brackets notation. Basically, this is just a shorthand notation for calling Add method multiple times by the compiler.

Note: The element initializers can be a simple value, an expression or an object initializer.

List<string> planets = new List<string>() { "Mercury", "Venus", "Earth" };

If no parameters are passed in the constructor, then parentheses () following the data type are optional.

List<string> planets = new List<string> { "Mercury", "Venus", "Earth" };

The following collection C# initializer uses C# object initializers to populate objects of the Planet class. Individual object initializers are enclosed in braces and separated by commas.

var planets = new List<Planet>
{
    new Planet() {Id = 1, Name ="Mercury"},
    new Planet() {Id = 2, Name = "Venus"},
    new Planet() {Id = 3, Name = "Earth"}
};

Run Demo


Add Items to a C# List

List<string> planets = new List<string> { "Mercury", "Venus", "Earth" };
string[] morePlanets = { "Mars", "Jupiter" };

Add()

Add method adds a new item at the end of a list and returns the item’s index. This method checks the capacity of the collection and automatically resize the List, if necessary, easier than adding an item to an array, which requires you to resize the array first.

Signature: void Add(T item)

planets.Add("Mars");
planets.Add("Jupiter");

Run Demo

OUTPUT

Mercury
Venus
Earth
Mars <-
Jupiter <-

Using add method to add individual objects of Planet class.

var planets = new List<Planet>();
planets.Add(new Planet(){Id =1, Name ="Mercury"});
planets.Add(new Planet(){Id = 2, Name = "Venus"});
planets.Add(new Planet(){Id = 3, Name = "Earth"});
planets.Add(new Planet(){Id =4, Name ="Mars"});

First, you use new keyword to create a new Planet object, which contains Id and Name property. You set values for the properties one at a time—one per row.

var jupiter = new Planet();
jupiter.Id = 5;
jupiter.Name = "4 line: Jupiter";
planets.Add(jupiter);

C# provides a convenient way to set properties, using object initializer syntax. This syntax looks like this:

//Above 4 lines vs below 1 line syntax. Same result
planets.Add(new Planet() { Id = 5, Name = "1 line: Jupiter" });

This frequently used syntax is more readable than the earlier option, where all the properties are set on the same line as the object is created.

Run Demo

AddRange()

You can use the AddRange method of the List<T> class to add multiple items all at once to the end of a collection. You can pass any IEnumerable collection, not just an array or another List.

Signature: void AddRange(IEnumerable<T> collection)

planets.AddRange(morePlanets);

OUTPUT

Mercury
Venus
Earth
Mars <-
Jupiter <-

Run Demo

Insert()

You can insert an item at a specific index in the list using the Insert method. The first parameter is the position and the second is the value being inserted. The Exception of type ArgumentOutOfRangeException is thrown, if the index set is larger than the number of items in the collection.

Signature: void Insert(int index, T item)

planets.Insert(2, "Mars");

OUTPUT

Mercury
Venus
Mars <-
Earth

Run Demo

InsertRange()

The InsertRange method is used to insert multiple items at a specific index in the list. The first parameter is the index position and the second is the collection to be inserted.

Signature: void InsertRange(int index, IEnumerable<T> collection)

planets.InsertRange(2, morePlanets);

OUTPUT

Mercury
Venus
Mars <-
Jupiter <-
Earth

Run Demo


Remove Items from a C# List

List<string> planets = new List<string> { "Mercury", "Venus", "Earth", "Mars" };

Remove()

The Remove method removes a particular item from the list. This method takes in one argument and removes the first occurrence of that argument. You need to pass the target item, not the index to remove.

Signature: bool Remove(T item)

planets.Remove("Venus");

OUTPUT

Mercury
Earth
Mars

Run Demo

RemoveAt()

The RemoveAt method removes an item from a specific location in the list by passing an index.

Signature: void RemoveAt(int index)

planets.RemoveAt(1);

OUTPUT

Mercury
Earth
Mars

Run Demo

RemoveRange()

The RemoveRange method removes all the items from a particular position in the list. The first parameter is the index, and the second parameter is the total number of items to be removed.

Signature: void RemoveRange(int index, int count)

planets.RemoveRange(1, 2);

OUTPUT

Mercury
Mars

Run Demo

Clear()

The Clear method removes all items in a list and sets its Count property to zero.

Signature: void Clear()

planets.Clear();

Run Demo


C# List Methods

List<string> planets = new List<string> { "Mercury", "Venus", "Earth" };

Contains()

Method checks and returns Boolean (True/False) value if contains the specified item in the list.

Signature: bool Contains(T item)

planets.Contains("Venus"); // Returns True

Run Demo

Sort()

Sorts the items in a list into ascending order by calling its Sort method.

Signature: void Sort()

planets.Sort();

OUTPUT

Earth
Mercury
Venus

Run Demo

TrimExcess()

Resizes the capacity to the actual number of items in the List<T>, if that number is less than 90 percent of current capacity.

Signature: void TrimExcess()

List<string> planets = new List<string>(6);
planets.Add("Mercury");
planets.Add("Venus");
planets.Add("Earth");

Console.WriteLine($"Capacity : {planets.Capacity}"); // Capacity before TrimExcess() is 6

planets.TrimExcess();

Console.WriteLine($"Capacity : {planets.Capacity}"); // Capacity after TrimExcess() is 3

Run Demo


C# List Properties

List<string> planets = new List<string> { "Mercury", "Venus" };

Count

To find out the total number of items in the list, use the Count property (derived from ICollection).

planets.Count; // Returns 2

Run Demo

Count()

The Count is an extension method introduced by LINQ that loops over all the items in an IEnumerable<> to find the count.

Required namespace: using System.Linq;

Signature: int IEnumerable<T>.Count<T>()

planets.Count(); // Returns 2

Run Demo

Capacity

Gets or sets the number of elements a list can hold, use the Capacity property.

The default capacity of a list is 0; if initialized as an empty list. As you can see in the following example.

planets = new List<string>();
planets.Capacity; // Returns 0

The capacity automatically assigned to a list is 4, even if initialized with a single item. As soon as the number of items in a list exceeds 4, the list is resized to accommodate more items. With every resizes the capacity is automatically doubled from 4 to 8, 16, 24 etc. Check the below example.

planets = new List<string> { "Mercury" };
planets.Capacity; // Returns 4

If you set the capacity during or after initialization of a list and the number of items exceeds that capacity, an ArgumentOutOfRangeException exception is thrown mentioning ‘capacity was less than the current size.’

planets = new List<string>() { "Mercury", "Venus", "Earth", "Mars" };
planets.Capacity = 3; // Set capacity to 3

Run Demo


Access Individual List Item

You can access the list items individually by using an indexer, which must be an integer type. This index position is used inside the square brackets [ ] when retrieving the value from the list. The first item can be accessed with an index value of 0.

Syntax

listName[index];
List<string> planets = new List<string> { "Mercury", "Venus", "Earth" };

planets[1]

OUTPUT

Venus

Run Demo


Processing C# List With Loops

The first statement declares a list named planets that contains 3 string values.

List<string> planets = new List<string> { "Mercury", "Venus", "Earth" };

Note: It doesn’t matter where you are modifying the collection. If a collection is modified while you are enumerating its members, you get exception.

for Loop

Here’s an example that shows how you can create, manipulate, and iterate through the contents of a List<T> collection using C# for loop:

for (var i = 0; i < planets.Count; i++)
{
    Console.WriteLine(planets[i]);
}

Run Demo

OUTPUT

Mercury
Venus
Earth

foreach Loop

If you use foreach to iterate through a List<T> collection, you cannot use the iteration variable to modify the contents of the collection. Additionally, you cannot call the Remove, Add, or Insert method in a C# foreach loop that iterates through a List<T> collection; any attempt to do so results in an InvalidOperationException exception.

Note: The foreach statement only allows reading from, not writing to, the collection.

foreach (var planet in planets)
    Console.WriteLine(planet);

Run Demo

OUTPUT

Mercury
Venus
Earth

ForEach Loop

Use of ForEach loop to iterate through a List<T> collection.

planets.ForEach(PrintValue);
//OR 
planets.ForEach(planet => Console.WriteLine(planet));

private static void PrintValue(string planet)
{
    Console.WriteLine(planet);
}

Run Demo

OUTPUT

Mercury
Venus
Earth


Processing C# List with LINQ

You can use LINQ to process List collection.

var planets = new List<Planet>
{
    new Planet() {Id = 1, Name ="Mercury"},
    new Planet() {Id = 2, Name = "Venus"},
    new Planet() {Id = 3, Name = "Earth"}
};
// Namespace required
using System.Linq;
// LINQ Method Expression
var planet = planets.Where(p => p.Id == 2).SingleOrDefault();
Console.WriteLine($"{planet.Id}, {planet.Name}");

// LINQ Query Expression
var planet = (from p in planets where p.Id == 3 select p).SingleOrDefault();
Console.WriteLine($"{planet.Id}, {planet.Name}");

Run Demo

OUTPUT

2, Venus
3, Earth


C# List Examples

This statement declares and initializes a list of 3 characters. Once the list is created, you can add items to the list.

List<char> grades = new List<char>(); // declaration & initialization
grades.Add('A');
grades.Add('B');
grades.Add('C');

Console.WriteLine(grades.Count); // Will return 3
Console.WriteLine(grades[1]); // Returns value B

//Code that retrieves the second value from the list
grades[1];

Run Demo

List<string> Vegetables = new List<string> { "Carrot", "Cucumber", "Tomato", "Onion", "Green Pepper" };

//Type inference with var keyword
var planets = new List<string> { "Mercury", "Venus", "Earth" };

List<int> integerValues = new List<int> (3) { 1, 2, 3 };

//Code that creates a list that holds decimal values
List<decimal> decimalValues = new List<decimal> { 13.2m, 20.74m, 8.34m };

Run Demo

List<int> integerValues = new List<int>(); //Declaration
integerValues = new List<int>() { 1, 2, 3, 4, 5, 6 }; // Initialization

List<int> moreIntegerValues = new List<int>() { 7, 8 }; //Declaration & Initialization

//Get single value from list
Console.WriteLine(integerValues[1]); //By Index and Prints 2

//Remove(), RemoveAt(), RemoveRange()
integerValues = new List<int>() { 1, 2, 3, 4, 5, 6 };

integerValues.Remove(2); // By Value
integerValues.RemoveAt(1); //By Index
integerValues.RemoveRange(1, 2);

integerValues.ForEach(o => Console.WriteLine(o));// print

//Add()
integerValues = new List<int>() { 1, 2, 3, 4, 5, 6 };

integerValues.Add(7);
integerValues.Add(8);

integerValues.ForEach(o => Console.WriteLine(o));// print

//AddRange()
integerValues = new List<int>() { 1, 2, 3, 4, 5, 6 };

integerValues.AddRange(moreIntegerValues);

integerValues.ForEach(o => Console.WriteLine(o)); // print

//Insert(), InsertRange()
integerValues = new List<int>() { 1, 2, 3, 4, 5, 6 };

integerValues.Insert(2, 13);
integerValues.InsertRange(2, moreIntegerValues);

integerValues.ForEach(o => Console.WriteLine(o));// print

//Contains(), Count, Count(), Capacity
integerValues = new List<int>() { 1, 2, 3, 6, 5, 4 };

Console.WriteLine(integerValues.Contains(2)); // Prints True
Console.WriteLine(integerValues.Count); // Property prints 6
Console.WriteLine(integerValues.Count()); // LINQ Method prints 6
Console.WriteLine(integerValues.Capacity); // Property prints 8
            
//Sort() 
integerValues.Sort();

integerValues.ForEach(o => Console.WriteLine(o));// print

//Clear() 
integerValues = new List<int>() { 1, 2, 3, 4, 5, 6 };

integerValues.Clear();
Console.WriteLine(integerValues.Count); // Prints 0

//Loops
integerValues = new List<int>() { 1, 2, 3, 4, 5, 6 };

//ForEach loop
integerValues.ForEach(o => Console.WriteLine(o));

//foreach loop
foreach (var value in integerValues)
    Console.WriteLine(value);

//for loop
for (var i = 0; i < integerValues.Count; i++)
{
     Console.WriteLine(integerValues[i]);
}

Run Demo


C# Reference | Microsoft Docs