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, 1Multi-Level Sorting with ThenBy
Sorting by a primary key, then breaking ties with a secondary key.
record Person(string Department, string Name);
List<Person> people = new List<Person>
{
new Person("Sales", "Fola"),
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: FolaGroupBy(): Grouping Elements
Splitting a sequence into groups based on a key.
record Student(string Name, string Grade);
List<Student> students = new List<Student>
{
new Student("Fola", "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: Fola, Jamal
// Grade B: ZainBest 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
At a glance
- Purpose
- Applications on the .NET platform
- File extension
- .cs
- Runs in
- .NET runtime
- Usually used with
- .NET SDK and libraries
Specifications & further reading
Related C# documentation
Lambda Expressions
A lambda expression is a compact way to represent an anonymous function - a block of code that can be passed around as a value, using the => (goes to) operator. Lambdas work with delegate types and functional interfaces like Func<> and Action<>, letting you write inline logic without a full named method. Lambdas are the foundation that makes LINQ's fluent, expressive query syntax possible.LINQ Basics: Where & Select
LINQ (Language Integrated Query) provides a consistent, declarative way to query collections, databases, and XML directly within C# syntax. Where() filters a sequence down to elements matching a condition, and Select() transforms each element into something new (a projection). Both are 'lazy' - they build a query that only actually runs when you iterate over the result or call something like ToList().LINQ Aggregation: Sum, Count, Average
LINQ provides built-in aggregation methods that reduce a sequence down to a single summary value: Count() for the number of elements, Sum() for a total, Average() for the mean, and Max()/Min() for extremes. Aggregate() is the general-purpose version, letting you define fully custom accumulation logic when the built-in methods aren't enough.LINQ Element & Quantifier Operators
Element operators retrieve a single item from a sequence: First()/FirstOrDefault() for the first match, Single()/SingleOrDefault() for exactly one match, with 'OrDefault' variants returning a default value instead of throwing when nothing matches. Quantifier operators return a bool describing the sequence as a whole: Any() checks if at least one element matches, and All() checks if every element matches.
A lambda expression is a compact way to represent an anonymous function - a block of code that can be passed around as a value, using the => (goes to) operator. Lambdas work with delegate types and functional interfaces like Func<> and Action<>, letting you write inline logic without a full named method. Lambdas are the foundation that makes LINQ's fluent, expressive query syntax possible.LINQ Basics: Where & Select
LINQ (Language Integrated Query) provides a consistent, declarative way to query collections, databases, and XML directly within C# syntax. Where() filters a sequence down to elements matching a condition, and Select() transforms each element into something new (a projection). Both are 'lazy' - they build a query that only actually runs when you iterate over the result or call something like ToList().LINQ Aggregation: Sum, Count, Average
LINQ provides built-in aggregation methods that reduce a sequence down to a single summary value: Count() for the number of elements, Sum() for a total, Average() for the mean, and Max()/Min() for extremes. Aggregate() is the general-purpose version, letting you define fully custom accumulation logic when the built-in methods aren't enough.LINQ Element & Quantifier Operators
Element operators retrieve a single item from a sequence: First()/FirstOrDefault() for the first match, Single()/SingleOrDefault() for exactly one match, with 'OrDefault' variants returning a default value instead of throwing when nothing matches. Quantifier operators return a bool describing the sequence as a whole: Any() checks if at least one element matches, and All() checks if every element matches.