List In C# – Explained With Examples

by Kenji Elzerman
The C data types list

C# has a lot of data types and some aren’t even used. We often use them without really knowing why we use them and what the data types are capable of. In this article: what is a List in C#? You might be using it a lot, but there is more to it to store just a few items and iterate through those items.

What Is A List In C#?

In C#, a List is a data structure that represents a collection of items that can be of any data type. Lists are implemented as classes in C#, and they provide methods for adding, removing, and modifying elements, as well as for accessing elements by their index. The List<T> class is a generic class, where T represents the type of elements in the list. This means that the list can hold any type of object, as long as it is specified when the list is created. A List in C# is very useful for storing and manipulating data flexibly and efficiently.

A List<T> is generic, where T is a type of element, list int, string, bool, etc. But you can only assign one type to T. It’s not possible to use different types in one list.

Below are a few examples that show how you can use the List<T> with different data types.

List<int> numbers = new() { 1, 2, 3, 4 };
List<string> countries = new() { "Australia", "Germany", "Spain " };
List<Product> products = new()
{
    new() { Name = "Laptop", Price = 999.95M },
    new() { Name = "Car", Price = 15000 },
    new() { Name = "TV", Price = 599 },
};

class Product {
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Iterating Through A List In C#

It’s nice that you now know how to declare and create a new list, but using it is also pretty nice.

A List is a list of items. You can loop, or iterate, through the list using the items one by one. There are several ways of doing this. I will be showing you the most common two: For and ForEach.

For

The For loop works with indexes. You start with an index, usually 0, and you work your way up to the highest-numbered index. You then use the current index to show, manipulate,  or use the item corresponding to that index. Here is an example:

List<string> countries = new() { "Australia", "Germany", "Spain " };

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

The for starts with declaring an int, which represents the current index. The start index is usually 0 unless you want to start further in the list. Then we define how far we want to go. In the example, I run this loop while the value of i is lower than the number of items in the list countries. Then I tell the for loop that after each round the value of i is incremented. The ++ means an increment of the value plus 1.

If you use a list with a complex type, like a product, you can use the For loop too:

List<Product> products = new()
{
    new() { Name = "Laptop", Price = 999.95M },
    new() { Name = "Car", Price = 15000 }, 
    new() { Name = "TV", Price = 599 }, 
};

for(int i = 0; i < products.Count; i++)
{
    Console.WriteLine(products[i].Name);
}

ForEach

The ForEach has the same idea as the for; it loops through the list in C#. Except this one does it a bit differently. Instead of using the indexes, it loops through the elements. In the example above, the item is of the type string. So it will start at the top get the first item (string) and place that in a variable, which we can use. In the next iteration, the next item is placed in that variable… And so on.

List<string> countries = new() { "Australia", "Germany", "Spain " };

foreach(string country in countries)
{
    Console.WriteLine(country);
}

If you use a list with a complex type, like a product, you can use the ForEach loop too:

List<Product> products = new()
{
    new() { Name = "Laptop", Price = 999.95M },
    new() { Name = "Car", Price = 15000 }, 
    new() { Name = "TV", Price = 599 }, 
};

foreach (Product product in products)
{
    Console.WriteLine(product.Name);
}

Manipulating A List In C#

It’s pretty easy to add, remove, or edit items in a list in C#. Unlike an array, a list can grow and shrink, hence the reason we usually prefer a list over an array.

A List<T> is an ordered collection of items, where each item has an index that represents its position in the list. This means that items are retrieved from the list based on their index, and not based on when they were added to the list. Therefore, the order of items in a list is always preserved.

If you want to use a data structure that implements FIFO behavior, you can use a Queue<T> in C#. If you want to use a data structure that implements LIFO behavior, you can use a Stack<T> in C#.

Besides adding and removing items, a list can also be ordered in different ways. From A-Z and Z-A. 

Adding

After you initialize the list in C# you can simply add new items with the method Add. This way the list can grow.

List<string> movies = new() { "The Matrix", "Shrek", "Inception" };
movies.Add("The Muppets");

The parameter of the Add needs to be the same type as the generic type. In the example, this is a string.

Removing

If you want to remove an item from the list you need to point to that particular item. In the example above it’s pretty simple: If you want to delete “The Matrix” item, simply use the Remove method and use the name (The Matrix) in the parameter. Like this:

List<string> movies = new() { "The Matrix", "Shrek", "Inception" };
movies.Add("The Muppets");

movies.Remove("The Matrix");

It’s a bit more tricky if you have a class as a list item. Like in a previous example I used a List<Product>, where Product is a class. If you want to remove an item from that list, you first have to grab the item and delete it.

Lists work with indexes. Each item in the list has an index that represents the position of that item. In the previous example, the indexes after removal of The Matrix are:

  1. Shrek
  2. Inception
  3. The Muppets

Indexes in lists always start with 0.

If you look at the List of products the indexes are:

List<Product> products = new()
{
    new() { Name = "Laptop", Price = 999.95M }, // Index 0
    new() { Name = "Car", Price = 15000 },      // Index 1
    new() { Name = "TV", Price = 599 },         // Index 2
};

If I want to delete the car, I need to retrieve the item with index 1 and then remove it. You can do that as follows:

List<Product> products = new()
{
    new() { Name = "Laptop", Price = 999.95M }, // Index 0
    new() { Name = "Car", Price = 15000 }, // Index 1
    new() { Name = "TV", Price = 599 }, // Index 2
};

Product toRemove = products[1];
products.Remove(toRemove);

Note that you can’t remove an item when you are iterating through that same list. This will give you errors.

Deleting item in list error - List In C# - Explained With Examples - Kens Learning Curve

Sorting

One of the advantages of a list in C# is sorting or ordering. With the method Sort, you can order items from A-Z, which we call ascending.

List<int> numbers = new() { 5,8,7,3,9 };
numbers.Sort();

Console.WriteLine(string.Join(", ", numbers));

The string.Join() is a method to easily concatenate items in a list into one string. This works for the example above. But if you have a list of complex types, like the Product, this doesn’t work.

The code example generates a string of 3, 5, 7, 8, and 9.

If you want to sort descending (Z-A, 9-0), you need to use a lambda expression in the Sort method:

List<int> numbers = new() { 5,8,7,3,9 }; 

numbers.Sort((x, y) => y.CompareTo(x)); 

Console.WriteLine(string.Join(", ", numbers));

In this example, a lambda expression is passed into the Sort method that compares two elements in reverse order using the CompareTo method. This sorts the elements in descending order instead of ascending order.

Using LINQ On List In C#

One of the benefits of List in C# is that you can use LINQ, which makes our lives a little bit easier. To include LINQ methods in a list we can search a list. We can also order a list a little bit easier.

To search a list we use the Where method. Add this to the list and add the correct predicate:

List<string> countries = new() { "Australia", "Germany", "Spain " };
List<string> countriesWithR = countries.Where(x => x.Contains("r")).ToList();

The Where returns an IEnumerable, not a List. This is the reason we add ToList() after the Where.

The result of the Where is a new list with only the countries that contain an ‘r’ in the name.

Searching in a list with a complex type, like the class Product, is a bit different. Here we can use the properties of the type of search:

List<Product> products = new()
{
    new() { Name = "Laptop", Price = 999.95M },
    new() { Name = "Car", Price = 15000 }, 
    new() { Name = "TV", Price = 599 }, 
};
List<Product> foundProducts = products.Where(x=>x.Name.Contains("a")).ToList();

Sorting with LINQ is a bit easier too. Instead of using the Sort method, we can use the OrderBy(Desc) method. The big difference between Sort and OrderBy is that Sort doesn’t have a return value, but OrderBy does. Simply calling Products.OrderBy(…) doesn’t do anything.

List<string> countries = new() { "Australia", "Germany", "Spain " };
List<string> sortedCountries = countries.OrderBy(x => x).ToList();

// With the products:
List<Product> products = new()
{
    new() { Name = "Laptop", Price = 999.95M },
    new() { Name = "Car", Price = 15000 }, 
    new() { Name = "TV", Price = 599 }, 
};
List<Product> sortedProducts = products.OrderBy(x => x.Name).ToList();

The Pros And Cons Of List In C#

Although the List in C# has a lot of pros there are some cons. Below are the advantages and disadvantages of using the List.

Advantages Of List In C#

  • Very easy to initialize and use. Mainly because of the Array-like performance.
  • The List will grow or shrink when you add or remove items. You don’t have to do anything for this to happen. This way, the List is pretty flexible.
  • Because the List is index-based, you can access the items inside the List pretty quickly.
  • The List<T> has a lot of methods to manage the items in the list. Add, remove, update, sort, and much more make it easy to manipulate the List.
  • You can use LINQ to iterate through or capture specific items in a List.

Disadvantages Of List In C#

  • Manipulating items in the middle of a list could cause performance issues.
  • The list has some memory overhead because of the dynamic resizing capabilities, especially when memory capacity is crucial.
  • If you want to use async functionalities with List, you might want to change some code: List is not thread-safe.
  • The sorting mechanism of the List isn’t the best one, causing performance issues when the List is big. This is also the case for searching.
  • A list does not support checks on unique data. It is possible to add unique items to a list. This could cause problems if you don’t want duplicate items in a List.

Conclusion On List In C#

You barely can’t work without the List<T> in your code. It’s one of those types you will always see and use. Yes, other collection types might be better for your situation. Because which collection type you use depends on what you need. But also take a look at the Dictionary<T, T>.

Still, the List<T> is essential in the C# work as it is powerful for storing temporary information when you run your application. Do not use the List in C# for caching. That’s a whole different story.

Related Articles

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

Table Of Contents
Kens Learning Curve