C# List
last modified January 15, 2024
In this article we show how to work with a List collection in C#.
C# List
C# List represents a strongly typed list of objects that can be accessed by index. It provides methods to search, sort, and manipulate lists.
C# List initializer
C# lists can be initialized with literal notation. The elements
are added on the right side of the assignment inside {}
brackets.
var words = new List<string> { "forest", "oak", "river", "falcon" }; Console.WriteLine(string.Join(", ", words));
In the example, we create a list of strings with list initializer.
var words = new List<string>{"forest", "oak", "river", "falcon"};
A new list is created. Between the angle brackets (<>
),
we specify the data type of the list elements.
Console.WriteLine(string.Join(", ", words));
To get a quick look at the contents of the list, we join all the values into a string, separated by comma.
$ dotnet run forest, oak, river, falcon
C# List collection expression
.NET 8 introduced a terse syntax to create and initialize a list.
List<string> words = ["forest", "oak", "river", "falcon"]; Console.WriteLine(string.Join(", ", words));
The elements of the list are placed inside a pair of square brackets
([]
). This syntax is shared by many programming languages.
C# List count elements
With the Count
property, we get the number of elements in the list.
List<int> vals = [0, 1, 2, 3, 4, 5]; Console.WriteLine($"There are {vals.Count} elements in the list");
The example counts the number of elements in the list.
Console.WriteLine($"There are {vals.Count} elements in the list");
Here we print the number of elements in the List.
$ dotnet run There are 6 elements in the list
C# List access elements
Elements of a list can be accessed using the index notation []
.
The index is zero-based.
List<int> vals = [0, 1, 2, 3, 4, 5]; Console.WriteLine(vals[0]); Console.WriteLine(vals[1]); Console.WriteLine(vals.Count - 1); Console.WriteLine(vals[^1]); Console.WriteLine(vals[^2]);
The example prints the first, second, and the last element of the list.
Console.WriteLine(vals.Count - 1);
To get the last element of the list, we count the number of elements and divide one.
Console.WriteLine(vals[^1]); Console.WriteLine(vals[^2]);
With the ^
operator, we can access elements from the end of the
list.
$ dotnet run 0 1 5 5 4
C# List add elements
The Add
method adds an element at the end of the list. The
AddRange
methods adds the elements of the specified collection to
the end of the list.
List<string> words = ["forest", "oak", "river", "falcon"]; words.Add("sky"); words.Add("ocean"); string[] words2 = ["owl", "hawk"]; words.AddRange(words2); Console.WriteLine(string.Join(',', words));
The example creates two lists and adds new elements to it.
words.Add("sky"); words.Add("ocean");
Two elements are added to the list with Add
.
string[] words2 = ["owl", "hawk"]; words.AddRange(words2);
With AddRange
method, we add another collection to the list.
$ dotnet run forest,oak,river,falcon,sky,ocean,owl,hawk
C# List insert elements
The Insert
method inserts an element into the list at the specified
index. The InsertRange
inserts the elements of a collection into
the list at the specified index.
List<string> words = ["forest", "oak", "river", "falcon"]; words.Insert(0, "sky"); words.Insert(words.Count, "cloud"); List<string> words2 =["water", "wave"]; words.InsertRange(2, words2); Console.WriteLine(string.Join(", ", words));
The example creates a new list of words and inserts new elements to it.
$ dotnet run sky, forest, water, wave, oak, river, falcon, cloud
C# List Contains
The Contains
method determines whether the element is in the list.
List<string> words = ["forest", "oak", "river", "falcon"]; if (words.Contains("oak")) { Console.WriteLine("The list contains the oak word"); }
In the example, we check if the oak
word is in the list.
C# List removing elements
The Remove
, RemoveAt
, RemoveAll
,
RemoveRange
, and Clear
methods can be used to remove
elements from a list.
List<int> nums = [0, 1, 2, -3, 4, -5, 6, 7, -8, 9, 10]; nums.RemoveAll(e => e < 0); Console.WriteLine(string.Join(", ", nums)); nums.Remove(0); nums.RemoveAt(nums.Count - 1); Console.WriteLine(string.Join(", ", nums)); nums.RemoveRange(0, 3); Console.WriteLine(string.Join(", ", nums)); nums.Clear(); Console.WriteLine("{0}", nums.Count);
In the example, we remove elements from the list of integers.
nums.RemoveAll(e => e < 0); Console.WriteLine(string.Join(", ", nums));
With RemoveAll
method, we remove all elements that satisfy the
given predicate; in our case, we remove all negative values.
nums.Remove(0);
The Remove
method removes the first occurrence of the 0 value.
nums.RemoveAt(nums.Count - 1);
With RemoveAt
, we remove the element at the given index.
nums.RemoveRange(0, 3);
The RemoveRange
method removes the given range of values from the
list. The parameters are the zero-based starting index of the range of elements
to remove and the number of elements to remove.
C# List ToArray
The ToArray
method copies the elements of a list into an array.
List<int> nums = [1, 2, 3, 4]; Console.WriteLine(nums.GetType()); var nums2 = nums.ToArray(); Console.WriteLine(nums2.GetType());
In the example, we create an array from a list. We print the type of both
containers with GetType
.
$ dotnet run System.Collections.Generic.List`1[System.Int32] System.Int32[]
C# List ForEach
The ForEach
method performs the specified action on each element
of a list.
List<string> words = ["forest", "oak", "river", "falcon"]; words.ForEach(Console.WriteLine); words.ForEach(word => Console.WriteLine(word.ToUpper()));
We call the ForEach
method twice on a list of words.
words.ForEach(Console.WriteLine);
We print all elements of the list.
words.ForEach(word => Console.WriteLine(word.ToUpper()));
Here we also print all elements of the list; the words are transformed to uppercase.
$ dotnet run forest oak river falcon FOREST OAK RIVER FALCON
C# loop List
There are several ways to loop over a C# list.
List<int> nums = [1, 2, 3, 4]; nums.ForEach(e => Console.WriteLine(e)); Console.WriteLine("********************"); foreach (int e in nums) { Console.WriteLine(e); } Console.WriteLine("********************"); for (int i = 0; i < nums.Count; i++) { Console.WriteLine(nums[i]); }
The example shows three ways of looping over a list in C#.
nums.ForEach(e => Console.WriteLine(e));
We loop over a list with ForEach
.
foreach(int e in nums) { Console.WriteLine(e); }
In this case, we use the foreach
statement.
for (int i = 0; i < nums.Count; i++) { Console.WriteLine(nums[i]); }
Finally, this is the classic for loop.
$ dotnet run 1 2 3 4 ******************** 1 2 3 4 ******************** 1 2 3 4
C# sort, reverse List
The Sort
method sorts the elements of a list, the
Reverse
method reverses the elements of the list.
List<int> nums = [2, 1, 5, 4, 3]; nums.Reverse(); Console.WriteLine(string.Join(',', nums)); nums.Sort(); Console.WriteLine(string.Join(',', nums));
The example reverses the elements of the list of integers and then sorts them.
$ dotnet run 3,4,5,1,2 1,2,3,4,5
C# List FindAll
The FindAll
method retrieves all the elements of a list that match
the conditions defined by the specified predicate. It returns a list containing
all the elements that match the conditions defined by the specified predicate,
if found; otherwise, an empty list.
A predicate is a method that returns a boolean value. To learn more about predicates, visit the C# Predicate tutorial.
List<int> vals = [-1, -3, 0, 1, 3, 2, 9, -4]; List<int> filtered = vals.FindAll(e => e > 0); Console.WriteLine(string.Join(',', filtered));
The example finds all positive elements.
List<int> filtered = vals.FindAll(e => e > 0);
The predicate is an expression that returns true for values greater than zero.
$ dotnet run 1,3,2,9
These are the positive values of the list.
C# List Find, FindLast, FindIndex, FindLastIndex
The Find
method returns the first occurrence of the element that
matches the given predicate. The FindLast
method returns the last
occurrence of the element that matches the given predicate.
The FindIndex
method returns the index of the first occurrence of
the element that matches the given predicate. The FindLastIndex
method returns the index of the last occurrence of the element that matches the
given predicate.
List<int> nums = [6, -2, 1, 5, 4, 3, 2, 9, -1, 7]; var found = nums.Find(e => e < 0); Console.WriteLine(found); var found2 = nums.FindIndex(e => e < 0); Console.WriteLine(found2); var found3 = nums.FindLast(e => e < 0); Console.WriteLine(found3); var found4 = nums.FindLastIndex(e => e < 0); Console.WriteLine(found4);
The example uses all the mentioned methods to find elements and indexes.
$ dotnet run -2 1 -1 8
C# List ConvertAll
The ConvertAll
method converts the elements in the current List to
another type, and returns a list containing the converted elements.
List<string> words = ["falcon", "owl", "sky", "hawk", "stork"]; List<string> uppedWords = words.ConvertAll(s => s.ToUpper()); List<int> lengths = words.ConvertAll(s => s.Length); Console.WriteLine(string.Join(", ", uppedWords)); Console.WriteLine(string.Join(", ", lengths));
In the example, we have a list of words. We convert the list to two other lists.
List<string> uppedWords = words.ConvertAll(s => s.ToUpper());
Here we convert the list to a list containing words transformed into uppercase.
List<int> lengths = words.ConvertAll(s => s.Length);
In the second case, the converted list contains integers that are the length of the words in the original list.
$ dotnet run FALCON, OWL, SKY, HAWK, STORK 6, 3, 3, 4, 5
In the second example, we have a separate squareRoot
method, which
is applied on the list of integers.
double squareRoot(int x) { return Math.Sqrt(x); } List<int> vals = [1, 4, 9, 16, 25]; Converter<int, double> converter = squareRoot; List<double> vals2 = vals.ConvertAll(converter); Console.WriteLine(string.Join(", ", vals2));
In the example, we create a new list by applying square root operation on the list of integers.
$ dotnet run 1, 2, 3, 4, 5
C# List shuffle
The following example randomly rebuilds a list of integer values.
List<int> vals = [1, 2, 3, 4, 5, 6, 7, 8]; vals.Shuffle(); var res = string.Join(" ", vals); Console.WriteLine(res); static class MyExtensions { private static readonly Random rng = new(); public static void Shuffle<T>(this IList<T> vals) { int n = vals.Count; while (n > 1) { n--; int k = rng.Next(n + 1); (vals[n], vals[k]) = (vals[k], vals[n]); } } }
In the example, we create a Shuffle
extension method. It shuffles
the elements in-place.
public static void Shuffle<T>(this IList<T> vals) { int n = vals.Count; while (n > 1) { n--; int k = rng.Next(n + 1); (vals[n], vals[k]) = (vals[k], vals[n]); } }
This is an implementation of the Fisher-Yates shuffling algorithm.
$ dotnet run 7 1 5 6 4 2 3 8 $ dotnet run 7 5 4 1 2 3 6 8 $ dotnet run 2 3 8 5 1 4 7 6 $ dotnet run 4 5 1 6 8 2 3 7
C# List TrueForAll
The TrueForAll
determines whether every element in the list
matches the conditions defined by the given predicate.
List<int> nums = [1, 2, 3, 4, 5, 6, 7, 8]; var res1 = nums.TrueForAll(e => e % 2 == 0); Console.WriteLine(res1); var res2 = nums.TrueForAll(e => e > 0); Console.WriteLine(res2);
In the example, we check if the elements in the list are all even and that they are all positive.
$ dotnet run False True
Not all elements are even and all elements are positive.
LINQ
Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of query capabilities directly into the C# language.
Via LINQ, C# exposes plenty of methods for working with List data.
C# List aggregate calculations
LINQ has extension methods to calculate aggregate calculations, such as min, max, or sum.
List<int> vals = [-1, 2, 1, -3, 7, -9, 5, 9, -4, 8]; var n1 = vals.Count; Console.WriteLine($"There are {n1} elements"); var n2 = vals.Count(e => e % 2 == 0); Console.WriteLine($"There are {n2} even elements"); var sum = vals.Sum(); Console.WriteLine($"The sum of all values is: {sum}"); var s2 = vals.Sum(e => e > 0 ? e : 0); Console.WriteLine($"The sum of all positive values is: {s2}"); var avg = vals.Average(); Console.WriteLine($"The average of values is: {avg}"); var max = vals.Max(); Console.WriteLine($"The maximum value is: {max}"); var min = vals.Min(); Console.WriteLine($"The minimum value is: {min}");
In the program, we use the Count, Sum, Average, Max, and Min methods.
$ dotnet run There are 10 elements There are 3 even elements The sum of all values is: 15 The sum of all positive values is: 32 The average of values is: 1.5 The maximum value is: 9 The minimum value is: -9
C# List ordering
To order data, we can use the OrderBy
and ThenBy
extension methods. Note that the methods create a new modified list; the
original list is not changed.
List<User> users = [ new ("John", "Doe", 1230), new ("Lucy", "Novak", 670), new ("Ben", "Walter", 2050), new ("Robin", "Brown", 2300), new ("Amy", "Doe", 1250), new ("Joe", "Draker", 1190), new ("Janet", "Doe", 980), new ("Albert", "Novak", 1930), ]; Console.WriteLine("sort ascending by last name and salary"); var sortedUsers = users.OrderBy(u => u.LastName).ThenBy(u => u.Salary); foreach (var user in sortedUsers) { Console.WriteLine(user); } Console.WriteLine("---------------------"); Console.WriteLine("sort descending by last name and salary"); var sortedUsers2 = users.OrderByDescending(u => u.LastName) .ThenByDescending(u => u.Salary); foreach (var user in sortedUsers2) { Console.WriteLine(user); } record User(string FirstName, string LastName, int Salary);
We have a list of users. The users are sorted first by their last names, then by their salaries.
var sortedUsers = users.OrderBy(u => u.LastName).ThenBy(u => u.Salary);
We sort the users by their last names and then by their salaries in ascending order.
var sortedUsers2 = users.OrderByDescending(u => u.LastName) .ThenByDescending(u => u.Salary);
Here, we sort the users by their last names and then by their salaries in descending order.
$ dotnet run sort ascending by last name and salary User { FirstName = Robin, LastName = Brown, Salary = 2300 } User { FirstName = Janet, LastName = Doe, Salary = 980 } User { FirstName = John, LastName = Doe, Salary = 1230 } User { FirstName = Amy, LastName = Doe, Salary = 1250 } User { FirstName = Joe, LastName = Draker, Salary = 1190 } User { FirstName = Lucy, LastName = Novak, Salary = 670 } User { FirstName = Albert, LastName = Novak, Salary = 1930 } User { FirstName = Ben, LastName = Walter, Salary = 2050 } --------------------- sort descending by last name and salary User { FirstName = Ben, LastName = Walter, Salary = 2050 } User { FirstName = Albert, LastName = Novak, Salary = 1930 } User { FirstName = Lucy, LastName = Novak, Salary = 670 } User { FirstName = Joe, LastName = Draker, Salary = 1190 } User { FirstName = Amy, LastName = Doe, Salary = 1250 } User { FirstName = John, LastName = Doe, Salary = 1230 } User { FirstName = Janet, LastName = Doe, Salary = 980 } User { FirstName = Robin, LastName = Brown, Salary = 2300 }
Source
List class - language reference
In this article we have worked with a C# List collection.
Author
List all C# tutorials.