Codectionary / Developer documentation / C#

LINQ Ordering & Grouping

OrderBy() and OrderByDescending() sort a sequence by a key you specify, with ThenBy() for secondary sort keys on ties. GroupBy() splits a sequence into groups based on a key selector, producing a sequence of groups where each group itself is enumerable and has a Key property identifying which group it represents.

Read the syntax

OrderBy selects an ascending sort key; OrderByDescending reverses it. ThenBy breaks ties after an existing ordering rather than replacing that ordering.

GroupBy produces groups identified by a key. Iterate each group to inspect its Key and members; query execution usually happens when you enumerate it.

Syntax

collection.OrderBy(keySelector).GroupBy(keySelector)

Examples

OrderBy and OrderByDescending

Sorting a sequence by a chosen key.

List<int> numbers = new List<int> { 5, 1, 4, 2, 3 };

var ascending = numbers.OrderBy(n => n).ToList();
Console.WriteLine(string.Join(", ", ascending));  // 1, 2, 3, 4, 5

var descending = numbers.OrderByDescending(n => n).ToList();
Console.WriteLine(string.Join(", ", descending));  // 5, 4, 3, 2, 1
  1. Sorting a sequence by a chosen key.
  2. OrderBy selects an ascending sort key; OrderByDescending reverses it. ThenBy breaks ties after an existing ordering rather than replacing that ordering.
  3. The two materialized queries print the integers in ascending and descending order. The source list itself is not changed.

Multi-Level Sorting with ThenBy

Sorting by a primary key, then breaking ties with a secondary key.

List<Person> people = new List<Person>
{
    new Person("Sales", "John"),
    new Person("Engineering", "Zain"),
    new Person("Engineering", "Amir")
};

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

foreach (var p in sorted) Console.WriteLine($"{p.Department}: {p.Name}");
// Engineering: Amir, Engineering: Zain, Sales: John

record Person(string Department, string Name);
  1. Sorting by a primary key, then breaking ties with a secondary key.
  2. OrderBy selects an ascending sort key; OrderByDescending reverses it. ThenBy breaks ties after an existing ordering rather than replacing that ordering.
  3. Department is the primary sort key; Name orders people within Engineering. The display places Amir and Zain before the Sales entry.

GroupBy(): Grouping Elements

Splitting a sequence into groups based on a key.

List<Student> students = new List<Student>
{
    new Student("John", "A"),
    new Student("Zain", "B"),
    new Student("Jamal", "A")
};

var byGrade = students.GroupBy(s => s.Grade);

foreach (var group in byGrade)
{
    Console.WriteLine($"Grade {group.Key}: {string.Join(", ", group.Select(s => s.Name))}");
}
// Grade A: John, Jamal
// Grade B: Zain

record Student(string Name, string Grade);
  1. Splitting a sequence into groups based on a key.
  2. OrderBy selects an ascending sort key; OrderByDescending reverses it. ThenBy breaks ties after an existing ordering rather than replacing that ordering.
  3. GroupBy places A students together and B students together. Each group’s Key and selected names are printed; the record type must be declared after top-level statements in Program.cs.

Best practices

  • Use ThenBy()/ThenByDescending() for secondary sort criteria instead of trying to encode multiple sort keys into one comparison
  • Remember each GroupBy() group is itself an IEnumerable<T> with a Key property - iterate or call .ToList() on it just like any other sequence
  • Combine GroupBy() with Select() to project each group into a summary (like a count or average) rather than keeping the full group
  • OrderBy() returns a new ordered sequence rather than sorting in place - unlike List<T>.Sort(), the original collection is untouched

Runtime & versions

.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

C# language reference

Specifications & further reading