How to sort with LINQ OrderBy in C#

The LINQ OrderBy() and OrderByDescending() methods sort a sequence without modifying the original collection. They return a new IOrderedEnumerable<T> that you can chain with ThenBy() for multi-key sorting.

Unlike List<T>.Sort(), which mutates the list in place, LINQ ordering always produces a new sequence.

OrderBy() uses a stable sort — elements with equal keys preserve their original order.

Basic Ascending Sort

C# Example Code
var numbers = new List<int> { 5, 1, 8, 3, 9, 2 };

var sorted = numbers.OrderBy(n => n).ToList();
Console.WriteLine(string.Join(", ", sorted));
// Output: 1, 2, 3, 5, 8, 9

Descending Sort

C# Example Code
var numbers = new List<int> { 5, 1, 8, 3, 9, 2 };

var descending = numbers.OrderByDescending(n => n).ToList();
Console.WriteLine(string.Join(", ", descending));
// Output: 9, 8, 5, 3, 2, 1

Sort a List of Strings

C# Example Code
var fruits = new List<string> { "banana", "apple", "cherry", "date" };

// Alphabetical (A–Z)
var az = fruits.OrderBy(f => f).ToList();
Console.WriteLine(string.Join(", ", az));
// Output: apple, banana, cherry, date

// Reverse alphabetical (Z–A)
var za = fruits.OrderByDescending(f => f).ToList();
Console.WriteLine(string.Join(", ", za));
// Output: date, cherry, banana, apple

Sort Objects by Property

C# Example Code
var people = new List<Person>
{
    new Person("Charlie", 35),
    new Person("Alice", 30),
    new Person("Bob", 25),
    new Person("Dave", 25)
};

// Sort by age ascending
var byAge = people.OrderBy(p => p.Age).ToList();
foreach (var p in byAge)
    Console.WriteLine($"{p.Name}: {p.Age}");

// Output:
// Bob: 25
// Dave: 25
// Alice: 30
// Charlie: 35

record Person(string Name, int Age);

Multi-Key Sort with ThenBy

C# Example Code
var people = new List<Person>
{
    new Person("Charlie", 35),
    new Person("Alice", 30),
    new Person("Bob", 25),
    new Person("Dave", 25)
};

// Primary: age ascending; secondary: name ascending
var sorted = people
    .OrderBy(p => p.Age)
    .ThenBy(p => p.Name)
    .ToList();

foreach (var p in sorted)
    Console.WriteLine($"{p.Name}: {p.Age}");

// Output:
// Bob: 25       ← age 25, alphabetically first
// Dave: 25      ← age 25, alphabetically second
// Alice: 30
// Charlie: 35

ThenByDescending

C# Example Code
var employees = new List<Employee>
{
    new Employee("Alice", "Engineering", 95000),
    new Employee("Bob",   "Marketing",   72000),
    new Employee("Carol", "Engineering", 88000),
    new Employee("Dave",  "Marketing",   85000)
};

// Sort by department A–Z, then by salary Z–A within department
var sorted = employees
    .OrderBy(e => e.Department)
    .ThenByDescending(e => e.Salary)
    .ToList();

foreach (var e in sorted)
    Console.WriteLine($"{e.Department} | {e.Name} | {e.Salary:C0}");

// Output:
// Engineering | Alice | $95,000
// Engineering | Carol | $88,000
// Marketing   | Dave  | $85,000
// Marketing   | Bob   | $72,000

record Employee(string Name, string Department, decimal Salary);

Sort Strings by Length

C# Example Code
var words = new List<string> { "banana", "kiwi", "apple", "fig", "cherry" };

// Sort by length, then alphabetically within same length
var sorted = words
    .OrderBy(w => w.Length)
    .ThenBy(w => w)
    .ToList();

Console.WriteLine(string.Join(", ", sorted));
// Output: fig, kiwi, apple, banana, cherry

Method Syntax vs Query Syntax

C# Example Code
var numbers = new List<int> { 5, 1, 8, 3, 9, 2 };

// Method syntax
var methodResult = numbers.OrderBy(n => n).ToList();

// Query syntax
var queryResult = (from n in numbers
                   orderby n ascending
                   select n).ToList();

// Multi-key in query syntax
var people = new List<Person> { /* ... */ };
var queryMulti = (from p in people
                  orderby p.Age ascending, p.Name descending
                  select p).ToList();

OrderBy vs List.Sort — Key Differences

OrderBy() (LINQ)List<T>.Sort()
SourceAny IEnumerable<T>List<T> only
Mutates originalNo — returns new sequenceYes — sorts in place
Return typeIOrderedEnumerable<T>void
Stable sortYesYes (.NET 5+)
Multi-keyThenBy() / ThenByDescending()Custom IComparer<T>
Use caseFunctional pipelineIn-place mutation
C# Example Code
var numbers = new List<int> { 5, 1, 8, 3, 9, 2 };

// LINQ — original list unchanged
var sorted = numbers.OrderBy(n => n).ToList();
Console.WriteLine("Original: " + string.Join(", ", numbers)); // 5, 1, 8, 3, 9, 2
Console.WriteLine("Sorted:   " + string.Join(", ", sorted));  // 1, 2, 3, 5, 8, 9

// List.Sort — mutates original
numbers.Sort();
Console.WriteLine("After Sort: " + string.Join(", ", numbers)); // 1, 2, 3, 5, 8, 9