OrderBy and Sorting

Vaibhav • September 11, 2025

Sorting is one of the most fundamental operations in programming. Whether you're displaying a list of names alphabetically, organizing products by price, or ranking scores from highest to lowest, sorting helps make data meaningful and usable. In LINQ, sorting is handled using the orderby keyword in query syntax and the OrderBy / OrderByDescending methods in method syntax. These tools allow you to sort data based on one or more criteria, in ascending or descending order, with full control over how comparisons are made.

Sorting with Query Syntax

The orderby keyword is used in LINQ query syntax to sort elements. By default, it sorts in ascending order. You can also specify descending to reverse the order.

List fruits = new List { "banana", "apple", "cherry", "apricot" };

var sorted = from fruit in fruits
             orderby fruit
             select fruit;

This query sorts the fruits alphabetically. The result will be: ["apple", "apricot", "banana", "cherry"]. The orderby clause compares strings using the default comparer, which is case-sensitive and culture-aware unless specified otherwise.

Descending Order in Query Syntax

To sort in descending order, simply add the descending keyword after the orderby clause.

var reversed = from fruit in fruits
               orderby fruit descending
               select fruit;

This query returns: ["cherry", "banana", "apricot", "apple"]. The sorting is reversed, but still uses the same comparison rules.

Sorting with Method Syntax

Method syntax uses the OrderBy and OrderByDescending methods. These are extension methods that take a lambda expression to specify the sorting key.

var sorted = fruits.OrderBy(f => f);

This is equivalent to the query syntax example above. It sorts the fruits in ascending order based on their string value.

var reversed = fruits.OrderByDescending(f => f);

This sorts the fruits in descending order. The lambda f => f simply returns the element itself, which is used as the sorting key.

Sorting by Property

When working with custom objects, you often want to sort by a specific property. Suppose you have a list of products:

class Product
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

List products = new List
{
    new Product { Name = "Laptop", Price = 999.99m },
    new Product { Name = "Tablet", Price = 499.50m },
    new Product { Name = "Phone", Price = 799.00m }
};

var sortedByPrice = products.OrderBy(p => p.Price);

This query sorts the products by their price in ascending order. The lambda p => p.Price extracts the price property from each product.

Sorting by Multiple Criteria

Sometimes you need to sort by more than one property. LINQ supports this using ThenBy and ThenByDescending.

var sorted = products
    .OrderBy(p => p.Price)
    .ThenBy(p => p.Name);

This query first sorts products by price. If two products have the same price, it then sorts them by name. This is useful for creating stable, predictable orderings.

Using orderby with Multiple Keys

Query syntax also supports multiple sorting keys. You can separate them with commas.

var sorted = from p in products
             orderby p.Price, p.Name
             select p;

This is equivalent to the method syntax example above. The products are sorted by price, then by name.

Custom Comparers

By default, LINQ uses the standard comparer for the type. For strings, this is culture-sensitive and case-sensitive. You can override this by providing a custom comparer.

var sorted = fruits.OrderBy(f => f, StringComparer.OrdinalIgnoreCase);

This query sorts fruits alphabetically, ignoring case. “Apple” and “apple” are treated as equal. This is useful for user-facing lists where case should not affect order.

Sorting with Computed Keys

You can sort by computed values, such as string length or derived properties.

var sortedByLength = fruits.OrderBy(f => f.Length);

This query sorts fruits by the number of characters in their name. The result will be: ["apple", "banana", "cherry", "apricot"] - depending on actual lengths.

Sorting with Index

While LINQ doesn’t expose index-based sorting directly, you can simulate it by projecting the index and sorting on it.

var indexed = fruits.Select((fruit, index) => new { fruit, index })
                    .OrderBy(x => x.index)
                    .Select(x => x.fruit);

This preserves the original order of the list. It’s useful when you need to sort temporarily and then restore the original sequence.

Sorting and Deferred Execution

Like other LINQ operations, sorting uses deferred execution. The query is not executed until you enumerate the result. This allows you to build complex queries without incurring performance costs until needed.

Note: If you sort a collection and then modify it before enumeration, the changes will affect the result. Always be mindful of when your query is executed.

Sorting and Stability

LINQ’s sorting methods are stable - elements with equal keys retain their original relative order. This is important when chaining multiple sorts or when the original order carries meaning.

Stability means that if two elements compare equal, their order in the result matches their order in the input. This helps avoid unexpected reordering.

Sorting and Performance

Sorting is generally efficient, but it can be costly for large datasets. LINQ uses optimized algorithms under the hood, but you should still be cautious when sorting large collections repeatedly.

If you need to sort a large collection multiple times, consider caching the sorted result using ToList() or ToArray(). This avoids recomputation and improves performance.

Sorting and Null Values

LINQ handles null values gracefully. When sorting strings or objects, null is treated as less than any non-null value. You can customize this behavior using comparers or conditional logic.

List names = new List { "Alice", null, "Bob" };

var sorted = names.OrderBy(n => n);

This query places null first, followed by “Alice” and “Bob”. If you want to exclude null values, use a where clause before sorting.

Sorting and Culture Sensitivity

String sorting is affected by culture. For example, in some cultures, “ä” is considered equal to “a”, while in others it’s distinct. LINQ allows you to specify the comparer to control this behavior.

var sorted = fruits.OrderBy(f => f, StringComparer.CurrentCulture);

This ensures that sorting feels natural to the user’s language and locale. For internal data, prefer Ordinal or OrdinalIgnoreCase for consistency.

You can change the current culture using Thread.CurrentThread.CurrentCulture. This affects all culture-sensitive operations, including sorting.

Summary

Sorting in LINQ is powerful, flexible, and easy to use. Whether you’re using query syntax or method syntax, you can sort by single or multiple keys, in ascending or descending order, with full control over comparison rules. By understanding how OrderBy, ThenBy, and custom comparers work, you can organize your data effectively for display, analysis, or further processing. Sorting is stable, culture-aware, and integrates seamlessly with other LINQ operations like filtering and projection.

In the next article, we’ll explore GroupBy Operations - how to categorize data into meaningful groups using LINQ.