C# Custom List Sorting

By FoxLearn 1/16/2025 2:25:16 AM   22
In C#, the List<T> class is a powerful collection type, providing built-in methods to efficiently sort and search data.

In this article, we’ll explore how to customize the sorting of a List<T> using the IComparable interface, IComparer interface, and Comparison<T> delegate in C#.

Default Sorting with Built-in Types

The Sort method of a List<T> automatically uses the CompareTo method for sorting, if the object implements the IComparable interface. Thankfully, many of the .NET built-in types, such as int, string, and DateTime, already implement IComparable, meaning you don’t have to do anything special to sort lists containing these types.

For example, sorting a list of strings in alphabetical order:

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

myList.Add("apple");
myList.Add("banana");
myList.Add("cherry");

myList.Sort();

foreach (string s in myList)
    Console.WriteLine(s);

Output:

apple
banana
cherry

Sorting Custom Objects with IComparable

When dealing with custom types, you need to implement the IComparable<T> interface in order to define how objects of your class are compared.

Let’s create a Person class, where we can compare people by their Age property.

public class Person : IComparable<Person>
{
    public string Name { get; set; }
    public int Age { get; set; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    // Implement CompareTo to compare persons by age
    public int CompareTo(Person other)
    {
        if (other == null) return 1;
        return Age.CompareTo(other.Age);
    }
}

Now, let’s create a list of Person objects and sort them by age:

List<Person> personList = new List<Person>
{
    new Person("Alice", 30),
    new Person("Bob", 25),
    new Person("Charlie", 35),
    new Person("Diana", 28)
};

personList.Sort();

foreach (Person person in personList)
    Console.WriteLine($"{person.Name}: {person.Age}");

Output:

Bob: 25
Diana: 28
Alice: 30
Charlie: 35

Custom Sorting with IComparer

Suppose you want to sort by a different property of the object, or in a different order, without modifying the object itself. By using the IComparer, you can define an external comparison logic.

public class PersonNameSorter : IComparer<Person>
{
    public int Compare(Person person1, Person person2)
    {
        if (person1 == null || person2 == null) return 0;
        return person2.Name.CompareTo(person1.Name);  // Reverse order for descending
    }
}

Now, we can use this custom comparer to sort the list:

personList.Sort(new PersonNameSorter());

foreach (Person person in personList)
    Console.WriteLine($"{person.Name}: {person.Age}");

Output:

Diana: 28
Charlie: 35
Bob: 25
Alice: 30

Sorting with a Comparison Delegate

An even more concise way to specify sorting logic is by using a Comparison<T> delegate, which allows you to pass a custom comparison function without needing to create a separate IComparer<T> class.

For example, let’s sort the Person list by Age in descending order using a Comparison<T>:

public int CompareByAgeDescending(Person person1, Person person2)
{
    return person2.Age.CompareTo(person1.Age);  // Reverse order for descending
}

personList.Sort(new Comparison<Person>(CompareByAgeDescending));

foreach (Person person in personList)
    Console.WriteLine($"{person.Name}: {person.Age}");

Output:

Charlie: 35
Alice: 30
Diana: 28
Bob: 25

Sorting in C# with the List<T> class is straightforward when using the default sorting mechanisms. However, when dealing with custom objects, you can take control of the sorting behavior by implementing the IComparable<T> interface, creating custom IComparer<T> implementations, or using the Comparison<T> delegate.