LINQ aggregate methods in C# — Sum, Count, Average, Min, Max, Aggregate
LINQ aggregate methods reduce a sequence down to a single value. They are the C# equivalent of SQL's SUM, COUNT, AVG, MIN, and MAX functions.
All aggregate methods execute immediately — they do not use deferred execution.
Sum
C# Example Code
var numbers = new List<int> { 1, 2, 3, 4, 5 };
int total = numbers.Sum();
Console.WriteLine(total); // 15
// Sum a property of each object
var products = new List<Product>
{
new Product("Laptop", 999.99m),
new Product("Mouse", 29.99m),
new Product("Keyboard", 79.99m)
};
decimal grandTotal = products.Sum(p => p.Price);
Console.WriteLine(grandTotal); // 1109.97
record Product(string Name, decimal Price);Count
C# Example Code
var numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
// Total count
int total = numbers.Count();
Console.WriteLine(total); // 6
// Count with a predicate
int evenCount = numbers.Count(n => n % 2 == 0);
Console.WriteLine(evenCount); // 3
// LongCount for very large sequences
long bigCount = numbers.LongCount();Average
C# Example Code
var scores = new List<double> { 88.0, 92.5, 76.0, 95.5, 84.0 };
double avg = scores.Average();
Console.WriteLine(avg); // 87.2
// Average of a property
var employees = new List<Employee>
{
new Employee("Alice", 75_000),
new Employee("Bob", 85_000),
new Employee("Carol", 95_000)
};
double avgSalary = employees.Average(e => e.Salary);
Console.WriteLine(avgSalary); // 85000
record Employee(string Name, int Salary);Min and Max
C# Example Code
var temperatures = new List<double> { 22.1, 18.5, 30.0, 25.3, 15.8 };
double min = temperatures.Min();
double max = temperatures.Max();
Console.WriteLine($"Min: {min}, Max: {max}"); // Min: 15.8, Max: 30
// Min/Max on object property
var products = new List<Product>
{
new Product("Laptop", 999.99m),
new Product("Mouse", 29.99m),
new Product("Keyboard", 79.99m)
};
decimal cheapest = products.Min(p => p.Price);
decimal mostExpensive = products.Max(p => p.Price);
Console.WriteLine($"Cheapest: {cheapest}, Most expensive: {mostExpensive}");
// Cheapest: 29.99, Most expensive: 999.99
record Product(string Name, decimal Price);MinBy and MaxBy (C# 10 / .NET 6+)
MinBy() and MaxBy() return the object with the minimum or maximum key, not just the value.
C# Example Code
var products = new List<Product>
{
new Product("Laptop", 999.99m),
new Product("Mouse", 29.99m),
new Product("Keyboard", 79.99m)
};
Product? cheapest = products.MinBy(p => p.Price);
Product? mostExpensive = products.MaxBy(p => p.Price);
Console.WriteLine(cheapest?.Name); // Mouse
Console.WriteLine(mostExpensive?.Name); // Laptop
record Product(string Name, decimal Price);Aggregate — Custom Reduction
Aggregate() is the general-purpose fold operation. It applies a function to each element, threading an accumulator through the sequence.
C# Example Code
var numbers = new List<int> { 1, 2, 3, 4, 5 };
// Running product: 1 * 2 * 3 * 4 * 5 = 120
int product = numbers.Aggregate((acc, n) => acc * n);
Console.WriteLine(product); // 120
// With a seed value (starting accumulator)
int sumPlusTen = numbers.Aggregate(10, (acc, n) => acc + n);
Console.WriteLine(sumPlusTen); // 25 (10 + 1+2+3+4+5)Aggregate with a Result Selector
C# Example Code
var words = new List<string> { "hello", "world", "from", "csharp" };
// Build a sentence, then transform the result
string sentence = words.Aggregate(
seed: new System.Text.StringBuilder(),
func: (sb, word) => sb.Append(sb.Length > 0 ? " " : "").Append(word),
resultSelector: sb => sb.ToString().ToUpper()
);
Console.WriteLine(sentence); // HELLO WORLD FROM CSHARPCombining Aggregates with GroupBy
C# Example Code
var orders = new List<Order>
{
new Order("Alice", "Electronics", 499.00m),
new Order("Bob", "Books", 19.99m),
new Order("Alice", "Books", 12.50m),
new Order("Bob", "Electronics", 299.00m),
new Order("Carol", "Electronics", 899.00m)
};
// Total revenue per category
var revenueByCategory = orders
.GroupBy(o => o.Category)
.Select(g => new
{
Category = g.Key,
Total = g.Sum(o => o.Amount),
Count = g.Count(),
Average = g.Average(o => o.Amount)
})
.OrderByDescending(x => x.Total);
foreach (var r in revenueByCategory)
Console.WriteLine($"{r.Category}: total={r.Total:C}, count={r.Count}, avg={r.Average:C}");
// Electronics: total=$1,697.00, count=3, avg=$565.67
// Books: total=$32.49, count=2, avg=$16.25
record Order(string Customer, string Category, decimal Amount);Null-Safe Aggregates
Aggregate methods on an empty sequence throw InvalidOperationException. Guard with a null-conditional or DefaultIfEmpty().
C# Example Code
var empty = new List<int>();
// Throws InvalidOperationException:
// int bad = empty.Sum(); // safe — Sum returns 0 for empty
// int bad = empty.Max(); // throws!
// Safe alternatives:
int safeMax = empty.DefaultIfEmpty(0).Max(); // 0
int? nullMax = empty.Any() ? empty.Max() : (int?)null;
Console.WriteLine(safeMax); // 0
Console.WriteLine(nullMax); // (blank — null)Quick Reference
| Method | Returns | Throws on empty? |
|---|---|---|
Sum() | Numeric total | No — returns 0 |
Count() | Element count | No — returns 0 |
Average() | Arithmetic mean | Yes |
Min() | Smallest value | Yes |
Max() | Largest value | Yes |
MinBy() | Object with smallest key | Yes |
MaxBy() | Object with largest key | Yes |
Aggregate(func) | Folded result | Yes (no seed) |
Aggregate(seed, func) | Folded result | No |