C# LINQ OrderByDescending: Sorting in Descending Order
c# linq orderbydescending: Learn how to use C# LINQ OrderByDescending to sort collections in descending order, handle null values, chain secondary sorts, and choose th...
c# linq orderbydescending requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
The OrderByDescending method in C# LINQ sorts a sequence in descending order based on a key selector function. It is the direct counterpart to OrderBy, which sorts ascending, and it is the operator you reach for whenever the largest values must appear first.
OrderByDescending Syntax and Basic Usage
The method takes a key selector as its first argument and returns an IEnumerable<T> containing the same elements in descending order.
using System.Linq; int[] scores = { 42, 17, 93, 55, 71 }; IEnumerable<int> ranked = scores.OrderByDescending(s => s);
The lambda s => s selects the element itself as the sort key. For a sequence of integers, this produces the order 93, 71, 55, 42, 17. The original array is not modified; OrderByDescending returns a new sequence.
Sorting by a Property with a Key Selector
The key selector is where OrderByDescending becomes useful for real objects. You supply a lambda that returns the property to sort on.
public record Product(string Name, decimal Price); var products = new[] { new Product("Keyboard", 89.99m), new Product("Mouse", 24.50m), new Product("Monitor", 299.00m) }; var byPriceDescending = products.OrderByDescending(p => p.Price);
Here the sequence is ordered by Price from highest to lowest: Monitor, Keyboard, Mouse. The selector can be any expression that returns a comparable value — a numeric property, a string, a DateTime, or a custom type that implements IComparable<T>.
Secondary Sorting with ThenByDescending
When two elements have the same sort key, OrderByDescending alone leaves their relative order as it appeared in the source. To break ties, chain ThenByDescending after the primary ordering.
var employees = new[] { new Employee("Ana", "Engineering", 120000), new Employee("Ben", "Engineering", 95000), new Employee("Cara", "Design", 110000) }; var sorted = employees .OrderByDescending(e => e.Salary) .ThenByDescending(e => e.Name);
The result is ordered by salary descending first; employees with identical salaries are then ordered by name descending. ThenBy and ThenByDescending can be chained repeatedly, and each subsequent call only affects elements that were tied by the previous key.
How OrderByDescending Handles Null Values
The default comparer treats null as smaller than any non-null value. In a descending sort, that places null keys at the end of the sequence.
var items = new[] { "banana", null, "apple", "cherry" }; var sorted = items.OrderByDescending(s => s);
The result is "cherry", "banana", "apple", then null last. If you need nulls first, supply a custom comparer that inverts this behavior, or filter nulls out before sorting with Where(x => x != null).
Performance and Deferred Execution
OrderByDescending returns a lazily evaluated IEnumerable<T>. The sort itself is not performed until the sequence is enumerated — by a foreach loop, ToList(), ToArray(), or another consuming operator.
var query = products.OrderByDescending(p => p.Price); // No sorting has happened yet var materialized = query.ToList(); // Sorting happens here
In LINQ to Objects, the sort is a stable O(n log n) operation. Stability means elements with equal keys keep their original relative order. The cost is dominated by the key selector being evaluated once per element and the comparison operations during the sort. For typical in-memory collections this is not a bottleneck, but if you sort a very large sequence repeatedly, consider whether the data could be maintained in sorted order at insertion time instead.
OrderByDescending vs In-Place Sorting
If you already have a List<T> and do not need the original order preserved, List<T>.Sort with a custom comparison can be more efficient because it sorts in place and avoids allocating a new sequence.
products.Sort((a, b) => b.Price.CompareTo(a.Price));
The tradeoff is that List.Sort is unstable, mutates the collection, and requires writing a comparison delegate. OrderByDescending is the better default for most code because it is declarative, works on any IEnumerable<T>, and leaves the source untouched. Choose in-place sorting only when the list is large, the original order is no longer needed, and allocation matters.
Common Mistakes and Avoiding Them
A frequent error is calling OrderByDescending and then ignoring the returned sequence, expecting the original collection to be sorted. Because the method is not in-place, the original collection remains unchanged.
Another mistake is using OrderByDescending on a property that does not implement IComparable or does not have a default comparer. In that case, pass an IComparer<T> explicitly:
var sorted = records.OrderByDescending(r => r.CustomField, new MyComparer());
Finally, remember that OrderByDescending is stable only in LINQ to Objects. If you are using a different LINQ provider, such as Entity Framework, the ordering is translated to the underlying query language and stability is not guaranteed.