When you need to sort a list, you don’t need to reinvent the wheel. You can use one of these three built-in methods for sorting a list:
- Use the OrderBy() Linq method. This returns an IOrderedEnumerable with the items in sorted order.
- Use the List.Sort() method if you need to sort the list in-place.
- Use AsParallel().OrderBy() to do a multithreaded sort on a big list for a performance boost.
In this article, I’ll show examples of using these three approaches for sorting a list.
Sort a list with OrderBy() (Linq)
The OrderBy() Linq method generates an IOrderedEnumerable with the list’s items sorted in ascending order. You can use this to sort lists of primitive values (such as integers) and complex objects. You have to pass in a lambda to specify which property to sort on (yes, even for list of primitives).
Here’s an example of using OrderBy() to sort people by name:
using System.Linq;
var people = new List<Person>()
{
new Person() { Name = "Bob", Age = 40},
new Person() { Name = "Linda", Age = 39},
new Person() { Name = "Tina", Age = 13},
new Person() { Name = "Gene", Age = 11},
new Person() { Name = "Louise", Age = 9}
};
foreach(var person in people.OrderBy(p => p.Name))
{
Console.WriteLine(person.Name);
}
Code language: C# (cs)
This outputs the people sorted by name in ascending order:
Bob
Gene
Linda
Louise
Tina
Code language: plaintext (plaintext)
OrderBy() + ToList()
Because OrderBy() returns an IOrderedEnumerable, you have to use ToList() to convert it to a List. This is useful when you want to replace the original list with the sorted list. Here’s an example:
using System.Linq;
var numbers = new List<int>()
{
8,3,5,1,2,1
};
numbers = numbers.OrderBy(n => n).ToList();
Console.WriteLine(string.Join(",", numbers));
Code language: C# (cs)
This outputs the numbers in ascending order:
1,1,2,3,5,8
Code language: plaintext (plaintext)
OrderByDescending() to sort in descending order
OrderBy() sorts in ascending order. To sort in descending order, use the OrderByDescending() Linq method in the same way you use OrderBy(). Here’s an example:
using System.Linq;
var numbers = new List<int>()
{
8,3,5,1,2,1
};
var sortedNumbers = numbers.OrderByDescending(n => n);
Console.WriteLine(string.Join(",", sortedNumbers));
Code language: C# (cs)
This outputs the numbers in descending order:
8,5,3,2,1,1
Code language: plaintext (plaintext)
Sort a list in-place with List.Sort()
Use List.Sort() if you want to sort the list in-place (which means it modifies the original list). It sorts in ascending order. You can optionally pass in a lambda to specify how to compare elements. Here’s an example:
var numbers = new List<int>()
{
8,3,5,1,2,1
};
numbers.Sort();
Console.WriteLine(string.Join(",", numbers));
Code language: C# (cs)
This outputs the integers in ascending order:
1,1,2,3,5,8
Code language: plaintext (plaintext)
Notice that you aren’t required to pass in a comparer lambda. It uses the type’s default comparer in that case. That makes List.Sort() a nice choice when sorting primitives – it’s less verbose than the rather strange OrderBy(x => x) syntax for primitives.
Sort by a property
Here’s an example of passing in a comparer lambda to List.Sort() to sort people by age in ascending order:
var people = new List<Person>()
{
new Person() { Name = "Bob", Age = 40},
new Person() { Name = "Linda", Age = 39},
new Person() { Name = "Tina", Age = 13},
new Person() { Name = "Gene", Age = 11},
new Person() { Name = "Louise", Age = 9}
};
people.Sort((a, b) => a.Age.CompareTo(b.Age));
foreach (var person in people)
{
Console.WriteLine($"{person.Name}, age {person.Age}");
}
Code language: C# (cs)
This outputs the people in sorted order by age:
Louise, age 9
Gene, age 11
Tina, age 13
Linda, age 39
Bob, age 40
Code language: plaintext (plaintext)
The syntax for the comparer lambda might seem a little confusing at first. With comparers, you’re given two elements (a and b) to compare and return the following:
- -1 if a should go first.
- 0 if a and b are equal.
- 1 if b should go first.
Tip: Use the property’s CompareTo() method to simplify things (instead of implementing the comparison logic yourself). Return the opposite to sort in descending order (i.e. b.Age.CompareTo(a.Age)).
Sort a big list with AsParallel().OrderBy()
If you’re running into performance problems when sorting a big list, try sorting the list with multiple threads. This works by partitioning the list, sorting the partitions concurrently, then merging the sorted partitions together into a sorted list. The simplest way to do this is by using the built-in AsParallel().OrderBy() (PLINQ). Here’s an example:
using System.Linq;
var bigList = GenRandomList<int>(size: 1_000_000);
var sortedBigList = bigList.AsParallel().OrderBy(i => i).ToList();
Code language: C# (cs)
Parallelization adds significant overhead, so don’t use this on small lists. It starts to outperform single-threaded sort at about 200k elements, and then gets up to 3x faster.
Here are the numbers from my simple perf comparison tests if you’re curious:
//Elements - method - seconds
//10k - Single - 0.0058573
//10k - Parallel - 0.0231644
//100k - Single - 0.0318935
//100k - Parallel - 0.0348231
//200k - Single - 0.0525700
//200k - Parallel - 0.0454412
//500k - Single - 0.1460155
//500k - Parallel - 0.0768617
//1m - Single - 0.3416384
//1m - Parallel - 0.1355227
//10m - Single - 4.6456977
//10m - Parallel - 1.5664340
Code language: C# (cs)