C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
190: Aggregate, Sum, Average, Min, Max
By now, you've spent a lot of time filtering and transforming data with LINQ. But in the real world, you rarely just want a filtered list; you usually want a number based on that list. Whether it's a total price, an average rating, or the highest score, that's where aggregation comes in.
I'm going to walk you through a simple scenario: we're building a small order processing module for a coffee shop. We have a list of items in a customer's cart, and we need to generate a summary for the receipt.
Defining our Coffee Order
First, let's set up a simple class and a list of data. I'll keep it lean so we can focus on the LINQ methods.
public class OrderItem
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
}
var cart = new List<OrderItem>
{
new OrderItem { Name = "Latte", Price = 4.50m, Quantity = 2 },
new OrderItem { Name = "Blueberry Muffin", Price = 3.25m, Quantity = 1 },
new OrderItem { Name = "Espresso", Price = 2.75m, Quantity = 1 },
new OrderItem { Name = "Croissant", Price = 3.50m, Quantity = 2 }
};
Calculating Totals and Averages
Now, I want to find the total amount the customer owes. My first instinct when I started with LINQ years ago was to just call Sum() on the collection. Let me show you the mistake I almost made here.
// This will NOT compile
// var total = cart.Sum();
The compiler will complain because cart is a list of OrderItem objects, not a list of numbers. LINQ doesn't know if I want to sum the prices, the quantities, or some magic combination of both. I have to provide a selector—a little lambda expression—to tell it exactly which property to target.
To get the total, I need to multiply price by quantity for each item and sum those results. Here is how I'll actually do it, along with getting the average item price:
// Total cost of all items
decimal totalCost = cart.Sum(item => item.Price * item.Quantity);
// Average price of a single unit of the items ordered
decimal averagePrice = cart.Average(item => item.Price);
Console.WriteLine($"Total: ${totalCost}");
Console.WriteLine($"Average Item Price: ${averagePrice:F2}");
Finding the Price Extremes
Usually, a manager wants to know what the most expensive item in a cart was, or perhaps the cheapest. Min and Max work exactly like Sum and Average; they just need that selector to know which property to look at.
decimal cheapest = cart.Min(item => item.Price);
decimal priciest = cart.Max(item => item.Price);
Console.WriteLine($"Cheapest item: ${cheapest}");
Console.WriteLine($"Most expensive item: ${priciest}");
Custom Logic with Aggregate
The methods we've used so far are "specialized" aggregators. But what if you want to do something that doesn't fit into a sum or an average? That's where Aggregate comes in. It's the Swiss Army knife of LINQ.
Let's say I want to create a comma-separated string of all the item names in the cart for a summary label. While string.Join is better for this specific case, using Aggregate is a great way to understand how "accumulation" works in C#.
string itemSummary = cart.Aggregate(
"", // The seed: where we start
(accumulator, item) => string.IsNullOrEmpty(accumulator)
? item.Name
: $"{accumulator}, {item.Name}"
);
Console.WriteLine($"Items ordered: {itemSummary}");
// Output: Items ordered: Latte, Blueberry Muffin, Espresso, Croissant
The Aggregate method takes a starting value (the seed) and a function that defines how to combine that seed with each element in the list. It's essentially a foreach loop condensed into a single expression. I don't use it as often as Sum or Average, but when you need a complex custom result from a collection, it's your best friend.
📋 Practical Task
Exercise: Student Grade Analytics
You are building a grade report tool for a teacher. You have a list of student scores, and you need to calculate the class statistics.
Your Task: Create a program that uses a list of Student objects (each having a Name and a Grade as a double). Using LINQ, calculate and print the following:
- The total sum of all grades in the class.
- The average grade of the class (formatted to 2 decimal places).
- The highest grade achieved.
- The lowest grade achieved.
- A single string listing all student names, separated by a pipe character (e.g., "Alice | Bob | Charlie"), using the
Aggregatemethod.
Starter Data:
public class Student
{
public string Name { get; set; }
public double Grade { get; set; }
}
var students = new List<Student>
{
new Student { Name = "Alice", Grade = 92.5 },
new Student { Name = "Bob", Grade = 78.0 },
new Student { Name = "Charlie", Grade = 88.5 },
new Student { Name = "Diana", Grade = 95.0 },
new Student { Name = "Ethan", Grade = 64.0 }
};There are no comments for now.