I originally posted this post on my blog a long time ago in a galaxy far, far away.
LINQ doesn't get new features with each release of the .NET framework. It simply works.
But this time, .NET 9 introduced two new LINQ methods: CountBy()
and Index()
. Let's take a look at them.
1. CountBy
CountBy groups the elements of a collection by a key and counts the occurrences of each key. With CountBy, there's no need to first group the elements of a collection to count its occurrences.
For example, let's count all movies in our catalog by release year, of course, using CountBy()
,
var movies = new List<Movie>
{
new Movie("Titanic", 1997, 4.5f),
new Movie("The Fifth Element", 1997, 4.6f),
new Movie("Forrest Gump", 1994, 4.3f),
new Movie("Terminator 2", 1991, 4.7f),
new Movie("Armageddon", 1998, 3.35f),
new Movie("Platoon", 1986, 4),
new Movie("My Neighbor Totoro", 1988, 5),
new Movie("Pulp Fiction", 1994, 4.3f),
};
var countByReleaseYear = movies.CountBy(m => m.ReleaseYear);
// πππ
foreach (var (year, count) in countByReleaseYear)
{
Console.WriteLine($"{year}: [{count}]");
}
// Output
// 1997: [2]
// 1994: [2]
// 1991: [1]
// 1998: [1]
// 1986: [1]
// 1988: [1]
record Movie(string Name, int ReleaseYear, float Rating);
CountBy()
returns a collection of KeyValuePair
with the key in the first position and the count in the second one.
Before .NET 9.0, we needed to use GroupBy with a second parameter to transform each group, like this,
var countByReleaseYear = movies.GroupBy(
x => x.ReleaseYear,
(releaseYear, movies) => new
// πππ
{
Year = releaseYear,
Count = movies.Count()
// πππ
});
CountBy()
has the same spirit of DistinctBy, MinBy, MaxBy, and other LINQ methods from .NET 6.0.
With these methods, we apply an action directly on a collection using a key selector. We don't need to filter or group a collection first to apply that action.
2. Index
Index projects every element of a collection alongside its position in the collection.
Let's "index" our catalog of movies,
var movies = new List<Movie>
{
new Movie("Titanic", 1998, 4.5f),
new Movie("The Fifth Element", 1997, 4.6f),
new Movie("Terminator 2", 1991, 4.7f),
new Movie("Avatar", 2009, 5),
new Movie("Platoon", 1986, 4),
new Movie("My Neighbor Totoro", 1988, 5)
};
foreach (var (index, movie) in movies.Index())
// ππ
{
Console.WriteLine($"{index}: [{movie.Name}]");
}
// Output
// 0: [Titanic]
// 1: [The Fifth Element]
// 2: [Terminator 2]
// 3: [Avatar]
// 4: [Platoon]
// 5: [My Neighbor Totoro]
record Movie(string Name, int ReleaseYear, float Rating);
Unlike CountBy()
, Index()
returns named tuples. It returns IEnumerable<(int Index, TSource Item)>
.
Before, we had to use the Select()
overload or roll our own extension method.
VoilΓ ! Those are two new LINQ methods in .NET 9.0: CountBy()
and Index()
.
The .NET team is bringing to the standard library the methods we needed to roll ourselves before.
Want to write more expressive code for collections? Join my Udemy course, Getting Started with LINQ, and master everything you need to work productively with LINQ β all in less than two hours!