In previous article, I mentioned Format Code in Visual Studio (With Indentation) but in this article, I have mentioned Select vs SelectMany in C# With an Example.

Select and SelectMany, both are projection operators.

  • Select: It selects value from collection.
  • SelectMany: It selects value from collection or collections, or we can say it performs cross join operation in SQL where it takes the cross product.

Select operator produces one result value for every source value while SelectMany produces a single result from multiple or nested collection and flatten the result.

Let's take a look at an example to understand difference between Select and SelectMany.

First we can define a Customer class with list of strings with their contact numbers:

        class Customer
        {
            public string Name { get; set; }
            public string Title { get; set; }
            public List<string> ContactNumbers { get; set; }
        }

Then create 3 customers for selection

List<Customer> customers = new List<Customer>() {
                new Customer { Name = "Ian", Title = "Mr", ContactNumbers = new List<string> { "45521152", "90555236", "9855215" } },
                new Customer { Name = "Alfred", Title = "Mr", ContactNumbers = new List<string> { "12556661", "15556731" } },
                new Customer { Name = "Lilly", Title = "Mrs", ContactNumbers = new List<string> { "3678452"} }
            };

We have 3 customers and 6 contact number.

Let’s write get each contact number with traditional way by looping each item.

using System;
using System.Linq;
using System.Collections.Generic;


public class Program
{
	public static void Main()
	{

		List<Customer> customers = new List<Customer>() {
				new Customer { Name = "Ian", Title = "Mr", ContactNumbers = new List<string> { "45521152", "90555236", "9855215" } },
				new Customer { Name = "Alfred", Title = "Mr", ContactNumbers = new List<string> { "12556661", "15556731" } },
				new Customer { Name = "Lilly", Title = "Mrs", ContactNumbers = new List<string> { "3678452"} }
		};

		foreach (var customer in customers)
		{
			foreach (var number in customer.ContactNumbers)
			{
				Console.WriteLine($"{number}");
			}
		}

		Console.ReadKey();
	}
	public class Customer
	{
		public string Name { get; set; }
		public string Title { get; set; }
		public List<string> ContactNumbers { get; set; }
	}
}

Output:

select-vs-selectmany-csharp

As you can see from above code and output, we were able to get all contacts, but We have to use double foreach loop to achieve this.

Let’s try using Select() to achieve the same result!

using System;
using System.Linq;
using System.Collections.Generic;


public class Program
{
	public static void Main()
	{

		List<Customer> customers = new List<Customer>() {
				new Customer { Name = "Ian", Title = "Mr", ContactNumbers = new List<string> { "45521152", "90555236", "9855215" } },
				new Customer { Name = "Alfred", Title = "Mr", ContactNumbers = new List<string> { "12556661", "15556731" } },
				new Customer { Name = "Lilly", Title = "Mrs", ContactNumbers = new List<string> { "3678452"} }
		};

               //add this line of code
		IEnumerable<List<string>> contactNumbers = customers.Select(x => x.ContactNumbers);


		foreach (var numbers in contactNumbers)
		{
			foreach (var number in numbers)
			{
				Console.WriteLine($"{number}");
			}
		}



		Console.ReadKey();
	}
	public class Customer
	{
		public string Name { get; set; }
		public string Title { get; set; }
		public List<string> ContactNumbers { get; set; }
	}
}

Output:

45521152
90555236
9855215
12556661
15556731
3678452

Still the same result and we have used double foreach again! Select method provides projection.

When we Select(x=> x.ContractNumbers), first it took the source object which is "Mr.Ian".

It adds Mr.Ian to list’s first item then, add each ContactNumbers to the first item as List.

select-vs-selectmany-csharp-3

Select() made a projection with the given property name per source object!

But there is still double foreach.

Let’s try SelectMany() and see if we can flatten these lists. In the end we just need a List of Contract numbers right?

static void Main(string[] args)
        {
            List<Customer> customers = new List<Customer>() {
                new Customer { Name = "Ian", Title = "Mr", ContactNumbers = new List<string> { "45521152", "90555236", "9855215" } },
                new Customer { Name = "Alfred", Title = "Mr", ContactNumbers = new List<string> { "12556661", "15556731" } },
                new Customer { Name = "Lilly", Title = "Mrs", ContactNumbers = new List<string> { "3678452"} }
            };

            //add select many
            IEnumerable<string> contactNumbers = customers.SelectMany(x => x.ContactNumbers);

            //use single foreach
            foreach (var numbers in contactNumbers)
            {
                Console.WriteLine($"{numbers}");
            }

            Console.ReadKey();
        }

We have just used SelectMany with the same projection property which is "ContractNumbers".

We need contract numbers in a single list from every source.

select-vs-selectmany-csharp-output-difference

Yes! SelectMany() has combined results to a single list for every contract number for every source.

You may also like to read:

Lambda expression in C# (With Examples)

Foreach() vs Parallel.Foreach() in C#

Convert C# Class to JSON with Example

Convert CSV to JSON in C#

Converting JSON to XML OR XML to JSON using C#