Back to Blog
C#

C# List Sort: List.Sort vs LINQ OrderBy

c# list sort: Learn how to sort List<T> in C# using List.Sort and LINQ OrderBy, including custom comparers, multiple keys, and performance tradeoffs.

C#List<T>SortingLINQComparer
Visual metaphor of a C# List being sorted, showing an unordered list transforming into an ordered sequence with arrows.

c# list sort requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

When you need to order a List<T> in C#, the framework gives you two primary approaches: the instance method List<T>.Sort() and the LINQ extension methods OrderBy() and OrderByDescending(). They look similar but behave differently in ways that matter for memory, stability, and how you chain operations. This article walks through each approach, shows how to apply custom comparers, and explains the tradeoffs so you can pick the right tool for the job.

Using List.Sort() for In-Place Sorting

The List<T>.Sort() method sorts the elements of the list in place, meaning the original list is reordered and no new list is created. It uses the default comparer for the type T unless you supply one.

var numbers = new List<int> { 5, 2, 8, 1, 9 }; numbers.Sort(); // numbers is now { 1, 2, 5, 8, 9 }

For a list of strings, the default comparer performs a culture-sensitive comparison. That can be surprising when you expect ordinal ordering, especially with mixed-case or accented characters. If you need a predictable, ordinal sort, pass StringComparer.Ordinal explicitly:

var words = new List<string> { "apple", "Banana", "cherry" }; words.Sort(StringComparer.Ordinal);

List.Sort() is an unstable sort for most implementations. That means if two elements compare as equal, their original relative order is not guaranteed to be preserved. This is rarely a problem for simple value types, but it becomes important when sorting objects by a key that is not unique.

Sorting with LINQ OrderBy and OrderByDescending

LINQ's OrderBy and OrderByDescending return a new IEnumerable<T> that yields elements in sorted order. They do not modify the original list. This is a functional style: you project a sorted sequence without mutating the source.

var numbers = new List<int> { 5, 2, 8, 1, 9 }; var sorted = numbers.OrderBy(n => n).ToList(); // numbers is unchanged; sorted is { 1, 2, 5, 8, 9 }

Because OrderBy is deferred, the sort is not executed until you enumerate the result. Calling ToList() forces the enumeration and materializes a new list. If you only need to iterate once, you can skip ToList() and use the IEnumerable directly.

OrderBy performs a stable sort. Equal elements retain their original order. This is a significant difference from List.Sort(). When you sort by a non-unique key, stable sorting gives you predictable results without needing a secondary sort key.

Custom Sorting with IComparer and Comparison<T>

Both List.Sort() and OrderBy accept custom comparison logic. For List.Sort(), you can pass an IComparer<T> or a Comparison<T> delegate. For OrderBy, you provide a key selector and optionally an IComparer<T> for that key.

Consider a Person class with Name and Age properties. To sort by Age ascending using List.Sort() with a Comparison<T>:

people.Sort((a, b) => a.Age.CompareTo(b.Age));

If you need the same comparison in multiple places, define an IComparer<Person>:

public class AgeComparer : IComparer<Person> { public int Compare(Person x, Person y) { return x.Age.CompareTo(y.Age); } } people.Sort(new AgeComparer());

With LINQ, you can sort by a property directly:

var sortedPeople = people.OrderBy(p => p.Age).ToList();

If the default comparison for the key type is not what you need, supply a custom comparer:

var sortedByName = people.OrderBy(p => p.Name, StringComparer.OrdinalIgnoreCase).ToList();

Sorting by Multiple Keys

Real-world sorting often requires a primary and secondary key. With List.Sort(), you combine comparisons in a single delegate:

people.Sort((a, b) => { int result = a.Age.CompareTo(b.Age); return result != 0 ? result : a.Name.CompareTo(b.Name); });

With LINQ, you chain ThenBy or ThenByDescending after OrderBy:

var sorted = people .OrderBy(p => p.Age) .ThenBy(p => p.Name) .ToList();

ThenBy preserves the stable order of the primary key, so it is often cleaner than writing a composite comparer. For descending secondary keys, use ThenByDescending.

Stability and Performance Considerations

Stability matters when you sort by a key that is not unique. List.Sort() is unstable, so two people with the same age may appear in any order after sorting. OrderBy is stable, so the original order of equal elements is preserved. If your application relies on the original order for ties, use LINQ's OrderBy or add a secondary sort key to List.Sort().

Performance also differs. List.Sort() sorts in place and typically uses less memory because it does not allocate a new list. It is an introsort implementation, which is O(n log n) on average. OrderBy creates an iterator and, when materialized with ToList(), allocates a new list and uses a stable sort algorithm (often a merge sort). The extra allocation can be significant for large lists, but the difference is rarely noticeable for typical in-memory collections.

Another consideration is whether you need the original list later. If you do, OrderBy is safer because it leaves the source untouched. If you want to reduce memory pressure and you do not need the original order, List.Sort() is more efficient.

Choosing the Right Sorting Approach

The decision between List.Sort() and LINQ OrderBy depends on your specific requirements:

CriterionList.Sort()LINQ OrderBy
Mutates original listYesNo
StabilityUnstableStable
Memory usageIn-place, minimalAllocates new sequence and list
Syntax for multiple keysManual comparerThenBy / ThenByDescending
Deferred executionNo, immediateYes, until enumerated
Best forLarge lists, memory-sensitive codeFunctional style, stable ordering

Use List.Sort() when you own the list, want to avoid extra allocations, and do not need stable ordering. Use OrderBy when you need a stable sort, want to keep the original list unchanged, or prefer a declarative chain of sorting keys. Both are valid; the right choice depends on the context of your application.

c# list sort: Practical Usage and Code Examples | RYUSLOG DEV