C# / LINQ

LINQ SelectMany Operator

SelectMany operator is used when we have a sequence of objects which has a collection property and we need to enumerate each item of child collection one by one.

SelectMany operator comes under Projection operators category of LINQ Query Operators.

Below is the syntax of SelectMany operator

public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector);
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);

There are three main overloads of SelectMany operator. Below are the usage of above overload methods.

  1. First overload is used to select collection property of target object.
  2. Second overload is used to select collection property of target object and it also provides the index of each object. For example, it provides index 0 for first item of sequence and index 1 for second item of sequence.
  3. Third overload provides very useful functionality. In addition to above, it also provides a custom function which we can use to create anonymous types and return that anonymous type in the result.

Let’s see all overload examples below:

C# LINQ SelectMany Examples

We have an employee object and employee object has a list of department collection.

public class Employee
{
    public int ID { get; set;  }
    public List<Department> Departments { get; set; }
}

public class Department
{
    public string Name { get; set; }
}

public static void Main(string[] args)
{
    List<Employee> employees = new List<Employee>();
    employees.Add(new Employee
    {
        ID = 1,
        Name = "Kapil",
        Departments = new List<Department>()
        {
            new Department { Name = "Marketing" },
            new Department { Name = "Sales"}
        }
    });
    employees.Add(new Employee
    {
        ID = 2,
        Name = "Raj",
        Departments = new List<Department>()
        {
            new Department { Name = "Advertisement" },
            new Department { Name = "Production"}
        }
    });
    employees.Add(new Employee
    {
        ID = 3,
        Name = "Ramesh",
        Departments = new List<Department>()
        {
            new Department { Name = "Production" },
            new Department { Name = "Sales"}
        }
    });
}

First Overload SelectMany Operator

In this problem scenario, we need to print each department name which are associated with each employee. In this case we need to use first overload of SelectMany operator.

var result = employees.SelectMany(w => w.Departments);
foreach(var dept in result)
{
    Console.WriteLine(dept.Name);
}

Marketing
Sales
Advertisement
Production
Production
Sales

Second Overload SelectMany Operator

In this problem scenario, we need to print each department name plus index value of each object of a sequence.

var result = employees.SelectMany((w, index) => w.Departments.Select(k => index.ToString() + "," + k.Name));
foreach (var dept in result)
{
    Console.WriteLine(dept);
}

Result
------
0,Marketing
0,Sales
1,Advertisement
1,Production
2,Production
2,Sales

Third Overload SelectMany Operator

In this problem scenario, we need to return a new object as anonymous type which has a reference of both the employee object and department of each employee.

var result = employees.SelectMany(w => w.Departments, (employee, department) => new { employee, department });
foreach (var item in result)
{
    Console.WriteLine(item.employee.Name + "," + item.department.Name);
}

Result
-------
Kapil,Marketing
Kapil,Sales
Raj,Advertisement
Raj,Production
Ramesh,Production
Ramesh,Sales

We have created an anonymous type which have a reference of employee object and department of each employee. In foreach, we print each employee name with its each department name.

SelectMany with Distinct Values

Sometimes we need to print distinct values from our child collection of target collection. Below is the sample query for the same.

var result = employees.SelectMany(w => w.Departments.Select(k => k.Name)).Distinct().ToList();
foreach (var item in result)
{
    Console.WriteLine(item);
}

Result
------
Marketing
Sales
Advertisement
Production

We have a list of duplicate department names in our collection. So we have used the Distinct query operator to filter out duplicate items from the result sequence.