Understanding Generic Lists in C#

c sharp generic listsStoring and managing collections of items is a routine programming task. Almost every application has to deal with a set of data with common characteristics. This set of data can be user profiles that are logged into a website, records from a database table or simple in-memory objects. In order to handle these sets of data, the .NET Framework contains special classes which are commonly known as collections.

Want to learn basics of C#? Take This Introductory Course

These collections are used to store and manage sets of data. There are two types of collections in the .NET Framework: The old non-generic collections which are located in System.Collections namespace and new strongly typed generic collections which are located in System.Collections.Generic namespace.

What is a Generic List (List<T>)?

A generic list is one of the many generic collections available in the System.Collections.Generic namespace and is most widely known for its ability to query a collection based on index. In technical terms, a generic list is written is referred as List<T> where T is the type of the item that this collection can store. List<T> collection implements both non-generic and generic IList and IList<T> interfaces, respectively. List<T> interface also implements the IEnumerable<T> interface. List<T> can be queried via LINQ queries.

For more information about LINQ, check out this course

Instantiating a List<T>

Instantiation or creating an object of a List<T> is a simple task. You simply have to specify the type of the item that generic list can store and the name of the variable. You can then call the constructor of the type List<T> to allocate a memory to the variable. List<T>’s constructor is overloaded to accept the elements during object definition. In the following example, a generic list of type string, named “countries”, has been instantiated and a few country names have been added in it during instantiation.

List<string> countries = new List<string> { “USA”, “UK”, “CANADA”, “AUSTRALIA”, “FRANCE”, “GERMANY” };

 

However, you can also instantiate the above list without adding elements. In that case elements will be added later on.

For example, you can instantiate a list of strings using the following code:

List<string> countries = new List<string>();

Adding Elements to List<T>

Add and Insert are the two basic methods for adding elements to a List<T>. However, you can also add a range of elements via AddRange and InsertRange methods. The difference between Add and Insert methods is that Add and AddRange methods add elements at the end of the list whereas Insert and InsertRange methods start adding elements at the specified index. Methods ending with “Range” take array of elements as parameter and add them all at once.

The following example, demonstrates the usage of these four methods.

List<string> countries = new List<string>();

 

countries.Add(“USA”);

countries.AddRange ( new [] {“UK”, “CANADA”, “AUSTRALIA”});

 

countries.Insert(1, “FRANCE”);

countries.InsertRange(3, new [] {“GERMANY”, “CHINA”, “RUSSIA”});
The Add method would first add “USA” and then AddRange would add “UK”, “CANADA” & “AUSTRALIA”. However, the Insert method would add “FRANCE” at the first Index as “1” has been passed as the first parameter which specifies the index. “FRANCE” would replace “UK” and all the elements after “FRANCE” would be shifted one index to the right. Similarly, when InsertRange is called with starting index 3, the elements would be stored starting from the index occupied by the element “CANADA”. If the above code is executed, the List would contain elements in this order: USA, FRANCE, UK, GERMANY, CHINA, RUSSIA, CANADA, and AUSTRALIA.

Interested in more List<T> functionalities? Try this course

Removing elements from List<T>

Removing elements from a List<T> is as simple as adding elements to it. List<T> type contains three basic methods for this purpose. The Remove method simply takes an element as a parameter and removes the matching element from the list. If the element is not present in the list, Remove returns false. RemoveAt method removes element from a specified index. RemoveRange takes two parameters: First is the starting index to remove elements and second is the number of elements to remove. These three methods are explained in the following example.

List<string> countries = new List<string> { “USA”, “UK”, “CANADA”, “AUSTRALIA”, “FRANCE”, “GERMANY” };

 

countries.Remove(“UK”);

countries.RemoveAt(1);

countries.RemoveRange(1, 2);

 

In the above example, the Remove(“UK”) method would remove “UK” from the list. Then, Remove(1) would remove “CANADA” from the list, because after removing “UK”, “CANADA” will be at first index. The RemoveRange(1,2) would remove “AUSTRALIA” and “FRANCE” since they will be  the first two elements starting from index 1 after “CANADA” is removed.

Enumerating List<T> elements via LINQ

A generic list List <T> implements the IEnumerable<T> interface which enables it to get enumerated via a foreach loop which is the simplest way to enumerate over a collection. The following example explains this:

List<string> countries = new List<string> { “USA”, “UK”, “CANADA”, “AUSTRALIA”, “FRANCE”, “GERMANY” };

 

foreach(string cont in countries)

{

Console.WriteLine(cont);

}

The real power of collections comes with fact that they can be queried via LINQ queries. For instance, you can use LINQ operator “where” to find all the countries which ends with “A” in their name. This is extremely easy to do with LINQ query operators and have been explained in the next example.

List<string> countries = new List<string> { “USA”, “UK”, “CANADA”, “AUSTRALIA”, “FRANCE”, “GERMANY” };

 

IEnumerable<string> endingwitha = countries.Where(c=> c.EndsWith(“a”, StringComparison.OrdinalIgnoreCase));

 

 

foreach (string cont in endingwitha)

{

Console.WriteLine(cont);

}

 

For above code snippet to work, System.Linq namespace has to be imported because “where” is purely a LINQ operator. A lambda expression is passed as parameter to the “where” operator. This lambda expression actually denotes the condition on the basis of which List<T> should be filtered. The “where” operator returns an object of interface type IEnumerable<T> which can then be used to query the elements as shown in the last example. The result of the above example would be “USA”, “CANADA” and “AUSTRALIA” because these are the elements that end with “a”.

Using OrderBy LINQ Operator on a List<T>

Another example of using LINQ operator with List<T> is the OrderBy operator, which orders the elements of a list based on the condition specified by lambda expression. The following example demonstrates this concept.

 

List<string> countries = new List<string> { “USA”, “UK”, “CANADA”, “AUSTRALIA”, “FRANCE”, “GERMANY” };

 

IEnumerable<string> orderedcoll = countries.OrderBy(c => c.Length);

foreach (string cont in orderedcoll)

{

Console.WriteLine(cont);

}

 

Here, OrderBy has been called on the “countries” collection and the predicate specified as a parameter says to order the collection on the basis of ascending order. The output will be all the elements in the collection starting from “UK” as first element (the element with the smallest length) and ending at “AUSTRALIA” as last element (the element with the largest length).

To learn more about a generic list <T> and LINQ operators in C#, check this detailed course.