Codectionary / Developer documentation / C#

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.

Read the syntax

Count, Sum, Average, Min and Max summarize a sequence. Selector overloads such as Sum(p => p.Price) first choose a property from each element.

Aggregate folds items into one accumulator, starting from the supplied seed. MaxBy returns an element with the greatest selected key, unlike Max on a numeric sequence.

Syntax

collection.Sum() / .Count() / .Average() / .Max() / .Min()

Examples

Basic Aggregations

The most common summary operations.

List<int> scores = new List<int> { 85, 92, 78, 90, 88 };

Console.WriteLine(scores.Count());    // 5
Console.WriteLine(scores.Sum());       // 433
Console.WriteLine(scores.Average());   // 86.6
Console.WriteLine(scores.Max());        // 92
Console.WriteLine(scores.Min());        // 78
  1. The most common summary operations.
  2. Count, Sum, Average, Min and Max summarize a sequence. Selector overloads such as Sum(p => p.Price) first choose a property from each element.
  3. The five scores produce a count of 5, sum 433, average 86.6, maximum 92 and minimum 78.

Aggregating with a Selector

Most aggregation methods accept a selector, letting you aggregate a property of complex objects directly.

List<Product> cart = new List<Product>
{
    new Product("Keyboard", 25),
    new Product("Mouse", 15),
    new Product("Monitor", 200)
};

double total = cart.Sum(p => p.Price);
Console.WriteLine(total);  // 240

Product mostExpensive = cart.MaxBy(p => p.Price)!;
Console.WriteLine(mostExpensive.Name);  // Monitor

record Product(string Name, double Price);
  1. Most aggregation methods accept a selector, letting you aggregate a property of complex objects directly.
  2. Count, Sum, Average, Min and Max summarize a sequence. Selector overloads such as Sum(p => p.Price) first choose a property from each element.
  3. Sum reads each Product.Price to calculate 240. MaxBy selects the Product whose Price is largest, so its Name is Monitor.

Aggregate(): Custom Accumulation

The general-purpose reduction method for logic the built-in aggregators don't directly cover.

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

int product = numbers.Aggregate(1, (acc, n) => acc * n);
Console.WriteLine(product);  // 120

string combined = numbers.Aggregate("", (acc, n) => acc + n + "-");
Console.WriteLine(combined);  // 1-2-3-4-5-
  1. The general-purpose reduction method for logic the built-in aggregators don't directly cover.
  2. Count, Sum, Average, Min and Max summarize a sequence. Selector overloads such as Sum(p => p.Price) first choose a property from each element.
  3. The first Aggregate multiplies 1 through 5 into 120. The second starts with empty text and appends each number plus a hyphen.

Counting with a Condition

Count() can accept a predicate directly, avoiding a separate Where() step.

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

int evenCount = numbers.Count(n => n % 2 == 0);
Console.WriteLine(evenCount);  // 4
  1. Count() can accept a predicate directly, avoiding a separate Where() step.
  2. Count, Sum, Average, Min and Max summarize a sequence. Selector overloads such as Sum(p => p.Price) first choose a property from each element.
  3. Count evaluates the even-number predicate for each item. Four numbers match, so evenCount prints 4.

Best practices

  • Use the selector overload (Sum(x => x.Property)) directly rather than chaining a separate Select() first - it is more concise and avoids an intermediate sequence
  • Use Count(predicate) instead of Where(predicate).Count() to skip creating an intermediate filtered sequence
  • Reach for Aggregate() only when the built-in Sum/Count/Average/Max/Min genuinely don't cover your accumulation logic - it is less readable for simple cases
  • Handle empty sequences carefully - Average(), Max(), and Min() throw an exception on an empty sequence, so check .Any() first or use the null-returning "OrDefault" variants where available

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