Code4IT

The place for .NET enthusiasts, Azure lovers, and backend developers

C# Tip: SelectMany in LINQ

2022-07-12 2 min read CSharp Tips
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!

🐧