C# Tip: SelectMany in LINQ
Just a second! π«·
If you are here, it means that you are a software developer. So, you know that storage, networking, and domain management have a cost .
If you want to support this blog, please ensure that you have disabled the adblocker for this site. I configured Google AdSense to show as few ADS as possible - I don't want to bother you with lots of ads, but I still need to add some to pay for the resources for my site.
Thank you for your understanding.
- Davide
There’s one LINQ method that I always struggle in understanding: SelectMany.
It’s actually a pretty simple method, but somehow it doesn’t stuck in my head.
In simple words, SelectMany works on collections of items that you can use, in whichever way, to retrieve other items.
Let’s see an example using the dear old for
loop, and then we will replace it with SelectMany
.
For this example, I’ve created a simple record type that represents an office. Each office has one or more phone numbers.
record Office(string Place, string[] PhoneNumbers);
Now, our company has a list of offices.
List<Office> myCompanyOffices = new List<Office>{
new Office("Turin", new string[]{"011-1234567", "011-2345678", "011-34567890"}),
new Office("Rome", new string[]{"031-4567", "031-5678", "031-890"}),
new Office("Dublin", new string[]{"555-031-4567", "555-031-5678", "555-031-890"}),
};
How can we retrieve the list of all phone numbers?
Iterating with a FOR-EACH loop
The most obvious way is to iterate over the collection with a for
or a foreach
loop.
List<string> allPhoneNumbers = new List<string>();
foreach (var office in myCompanyOffices)
{
allPhoneNumbers.AddRange(office.PhoneNumbers);
}
Nothing fancy: we use AddRange
instead of Add
, just to avoid another inner loop.
Using SelectMany
You can do the same thing in a single line using LINQ’s SelectMany
.
List<string> allPhoneNumbers = myCompanyOffices.SelectMany(b => b.PhoneNumbers).ToList();
This method aggregates all the PhoneNumbers elements in an IEnumerable<string>
instance (but then we need to call ToList
to convert it).
Of course, always check that the PhoneNumbers
list is not null
, otherwise it will throw an ArgumentNullException
.
The simplest way is by using the ??
operator:
allPhoneNumbers = myCompanyOffices.SelectMany(b => b.PhoneNumbers ?? Enumerable.Empty<string>()).ToList();
Wrapping up
Easy, right? I don’t have anything more to add!
Happy coding!
π§