My Favorite C# Features Part 2: LINQ
Jeffrey T. Fritz
Posted on March 10, 2021
Working with collections in any programming language always ends up with some sort of loop structure and ugly code to find an object, work on several objects, and exit the loop. This is why I really enjoy using LINQ with C# -- all of this looping and aggregation code is hidden from me by the compiler and I can focus on writing the code that I actually need to get and work with data in a collection. In this post, I'll review some of my favorite LINQ features that make me more productive in working with collections of data.
Throughout the samples below, we'll work with this collection of Hat objects. It's a real collection, and yes I do have these hats IRL. You can see a large selection of my hat collection at https://hats.csharpfritz.com
public class Hat {
// A name I've assigned to the hat
public string Name { get; set; }
// The year I acquired the hat
public int Year { get; set; }
// Theme of the hat: Sports, Movies, Tech, etc
public string Theme { get; set; }
}
public static class HatCollection {
public static readonly Hat[] Items = new Hat[] {
new Hat { Name="Camp Crystal Lake", Year=2020, Theme="Movies" },
new Hat { Name="Marauder's Map", Year=2020, Theme="Movies" },
new Hat { Name="Super C#", Year=2018, Theme="Tech" },
new Hat { Name="Dunder Mifflin", Year=2018, Theme="TV" },
new Hat { Name="Space X", Year=2019, Theme="Tech" },
new Hat { Name="Phillies 2008 World Series", Year=2008, Theme="Sports" },
new Hat { Name="The Flash", Year=2021, Theme="TV" }
};
}
Where - Find Some Data and Return It
What good is a collection of data if you can't search through it quickly with just a 1 line command? The Where
method can be used to quickly find the subset of items that meet your condition.
Given the collection of hats, we could return just those hats that were acquired in 2020 with this command:
var twentyTwentyHats = HatCollection.Items.Where(h => h.Year==2020);
// Returns "Camp Crystal Lake" and "Marauder's Map" hat objects
The contents of the Where
method are called a lambda expression. You define a lambda with a variable that will capture one of the items in the collection, add a 'fat arrow' and then the operation you want to process on that item. In the case of a Where
method, we are testing for a condition and returning a true or false boolean value to indicate if the item should be returned.
In this case, we are testing if the Year
property of the Hat
is 2020.
Are ANY of these Hats from before 2010?
The Any
method is a simple check to return a true or false boolean value indicating if a condition is met. If we want to search the collection for hats that are from before 2010, we could use this expression:
var olderThanTwentyTen = HatCollection.Items.Any(h => h.Year < 2010);
// Returns true due to the presence of the 2008 Phillies hat
The Any
method can operate quickly as it will stop looping through the collection as soon as the condition is met.
Count those hats
Aggregate methods are available that allow you to count, sum, min, max, and average values inside the collection. In addition to simply counting all of the items in the collection, we can provide a test method to count only those items that pass that test.
var totalHats = HatCollection.Items.Count();
// This returns 7.. but honestly,
// Fritz's hat collection is more than 100
var techHatsCount = HatCollection.Items.Count(h => h.Theme == "Tech");
// This will return 2 for "Super C#" and "Space X"
Sorting done simply
Sorting is one of those computer science gotcha questions that ALWAYS comes up in an interview and nobody likes it. When it comes to sorting collections in memory, I just let the experts who built .NET do it for me by using the OrderBy
and OrderByDescending
methods. Simply provide a selector method that returns the property or value to order by and LINQ will return to you a collection of your objects in the order desired:
var newestHatsFirst = HatCollection.Items.OrderByDescending(h => h.Year);
var orderByTheme = HatCollection.Items.OrderBy(h => h.Theme);
Did you know, you can chain these sort method together, or even connect them with a Where
method to create a more interesting query?
var techHatsNewestFirst = HatCollection.Items
.Where(h => h.Theme == "Tech")
.OrderByDescending(h => h.Year);
// This returns the "Space X", "Super C#" hat objects
Project your output with Select
Just like in SQL, there is a Select
method that can be used with LINQ to transform our collection from one object to another. Perhaps we just want an array of the hat names... easy:
var hatNames = HatCollection.Items.Select(h => h.Name);
You can use select to convert to another type, an anonymous type, or tuples. Use Select
to give you the shape and format of the data you need.
Group By FTW!
It's nice to be able to sort and filter your data, but the real power comes in when you summarize a collection. Let's use the GroupBy
feature to summarize the number of hats in the collection by theme:
var totalByTheme = HatCollection.Items
.GroupBy(h => h.Theme)
.Select(g => new {Theme=g.Key, Count=g.Count() });
foreach (var item in totalByTheme)
{
Console.WriteLine($"Theme: {item.Theme}, Count: {item.Count}");
}
/*
Outputs:
Theme: Movies, Count: 2
Theme: Tech, Count: 2
Theme: TV, Count: 2
Theme: Sports, Count: 1
*/
This GroupBy
delivers a collection of grouped objects with a Key
property that contains the value grouped by, in this case the Theme
property. We can then chain the Select
method to project these groupings into a summary collection with the themes and the count of hats that belong to each theme.
Summary
This is just the beginnings of the cool things you can do with LINQ. Put together with an object-relational mapper tool like Entity Framework and you have a very cool way to query your database.
Did you know, I host a weekly live stream on the Visual Studio Twitch channel teaching the basics of C#? Tune in on Mondays at 9a ET / 1400 UTC for two hours of learning in a beginner-friendly Q+A format with demos and sample code you can download. I recently had an episode about LINQ that you can find on YouTube:
Looking to get started learning C#? Checkout our free on-demand courses on Microsoft Learn!
Posted on March 10, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.