What is a List?

A List in C# is a dynamic data structure that allows storing multiple elements of the same type while providing flexibility in size and built-in methods for manipulation. Unlike arrays, which have a fixed size, lists can grow and shrink dynamically based on the number of elements they hold.

Lists are part of the System.Collections.Generic namespace and provide a more efficient and convenient way to work with collections of data compared to arrays, especially when frequent additions and removals are required.

Creating a List

To use a list in C#, you need to include the System.Collections.Generic namespace and define the type of elements the list will store.

using System.Collections.Generic;

List<int> myList = new List<int>();

//You can also initialize a list with predefined values:
List<int> myList = new List<int> { 10, 20, 30, 40, 50 };

This creates a list containing five integer values.

Lists Can Store Any Object Type

Lists in C# are generic, meaning they can store objects of any type, including custom objects:

class Person 
{ 
    public string Name { get; set; } 
    public int Age { get; set; } 
} 

List<Person> people = new List<Person> 
    { 
        new Person { Name = "Alice", Age = 30 }, 
        new Person { Name = "Bob", Age = 25 } 
    };

This makes lists highly flexible for working with complex data structures.

Lists and IEnumerable

Lists implement the IEnumerable<T> interface, which means they can be iterated using foreach and used in LINQ queries:

IEnumerable<int> enumerableList = myList;
foreach (var item in enumerableList)
{
    Console.WriteLine(item);
}

Because lists implement IEnumerable<T>, they work seamlessly with LINQ operations, making them powerful for querying and filtering data efficiently.

Adding Items to a List

Unlike arrays, lists allow you to dynamically add elements using the Add() method:

myList.Add(60);

You can also add multiple elements at once using AddRange():

myList.AddRange(new int[] { 70, 80, 90 });

If you need to insert an item at a specific position, use Insert():

myList.Insert(2, 25); // Inserts 25 at index 2

Removing Items from a List

You can remove elements from a list using the Remove() method by specifying the value:

// Removes the first occurrence of 30
myList.Remove(30);

To remove an item at a specific index, use RemoveAt():

// Removes the item at index 1
myList.RemoveAt(1);

To remove all elements, use Clear():

myList.Clear();

Accessing Elements in a List

Just like arrays, lists use zero-based indexing to access elements:

int firstElement = myList[0]; 
int secondElement = myList[1];

Attempting to access an index that does not exist will cause an ArgumentOutOfRangeException.

Searching in a List

To find an element in a list, you can use:

Contains() method:

if (myList.Contains(20))
{
    Console.WriteLine("Element found!");
}

IndexOf() method:

int index = myList.IndexOf(40);
if (index != -1)
{
    Console.WriteLine($"Element found at index {index}");
}

Find() method for custom objects:

Person foundPerson = people.Find(p => p.Name == "Alice");
if (foundPerson != null)
{
    Console.WriteLine($"Found: {foundPerson.Name}, Age: {foundPerson.Age}");
}

FindAll() method for multiple matches:

List<Person> results = people.FindAll(p => p.Age > 25);
foreach (var person in results)
{
    Console.WriteLine(person.Name);
}

Sorting and Reversing a List

Lists provide built-in methods to sort and reverse elements.

Sorting a list:

myList.Sort();

Reversing a list:

myList.Reverse();

Concatenating Lists

You can concatenate lists by using the AddRange() method or LINQ.

Using AddRange():

List<int> list1 = new List<int> { 1, 2, 3 };
List<int> list2 = new List<int> { 4, 5, 6 };
list1.AddRange(list2);

Using LINQ:

List<int> combinedList = list1.Concat(list2).ToList();

Unlike arrays, concatenating lists is more efficient because lists manage their memory dynamically.

Performance Considerations

While lists are more flexible than arrays, they have some performance trade-offs:

  1. Memory Overhead – Lists require more memory than arrays because they dynamically resize.
  2. Resizing Cost – When a list exceeds its current capacity, it resizes by allocating a larger array and copying existing elements, which can impact performance.
  3. Random Access Speed – Lists provide O(1) access time, similar to arrays, but inserting or deleting elements can be O(n) in the worst case.

If you have a known fixed-size dataset, use arrays for better performance. If you require dynamic resizing and frequent modifications, lists are the better choice.

Conclusion

Lists in C# provide a powerful alternative to arrays, offering dynamic resizing and built-in methods for managing elements efficiently. They are ideal for scenarios where the number of elements is unknown or changes frequently. Additionally, lists can store custom objects and implement IEnumerable<T>, allowing seamless integration with LINQ queries. Lists also provide efficient searching methods, making them ideal for querying data. However, they come with memory and resizing trade-offs, so choosing between lists and arrays depends on the specific use case.