System.Linq.Join

This page documents the Join extension method in the System.Linq namespace.

Summary

Correlates the elements of two sequences based on matching keys. This method performs an inner join.

Syntax

public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
    this IEnumerable<TOuter> outer,
    IEnumerable<TInner> inner,
    Func<TOuter, TKey> outerKeySelector,
    Func<TInner, TKey> innerKeySelector,
    Func<TOuter, TInner, TResult> resultSelector
);
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
    this IEnumerable<TOuter> outer,
    IEnumerable<TInner> inner,
    Func<TOuter, TKey> outerKeySelector,
    Func<TInner, TKey> innerKeySelector,
    Func<TOuter, TInner, TResult> resultSelector,
    IEqualityComparer<TKey> comparer
);

Parameters

  • outer: An IEnumerable<TOuter> whose elements to join to the inner sequence.
  • inner: An IEnumerable<TInner> whose elements to join to the outer sequence.
  • outerKeySelector: A function to extract the join key from each element of the outer sequence.
  • innerKeySelector: A function to extract the join key from each element of the inner sequence.
  • resultSelector: A function to create a result element from two matching elements from the outer and inner sequences.
  • comparer: An IEqualityComparer<TKey> to compare keys.

Return Value

An IEnumerable<TResult> that contains elements of type TResult that are obtained by performing an inner join on the two sequences.

Exceptions

  • ArgumentNullException: outer, inner, outerKeySelector, or innerKeySelector is null.

Remarks

The Join method is an implementation of a nested loop join algorithm. For each element in the outer sequence, it searches the inner sequence for elements that have a matching key. The join is performed based on the keys extracted by the outerKeySelector and innerKeySelector functions.

Example

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

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

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int DepartmentId { get; set; }
}

public class Program
{
    public static void Main(string[] args)
    {
        var departments = new List<Department>
        {
            new Department { Id = 1, Name = "HR" },
            new Department { Id = 2, Name = "Engineering" },
            new Department { Id = 3, Name = "Sales" }
        };

        var employees = new List<Employee>
        {
            new Employee { Id = 101, Name = "Alice", DepartmentId = 2 },
            new Employee { Id = 102, Name = "Bob", DepartmentId = 1 },
            new Employee { Id = 103, Name = "Charlie", DepartmentId = 2 },
            new Employee { Id = 104, Name = "David", DepartmentId = 3 },
            new Employee { Id = 105, Name = "Eve", DepartmentId = 2 }
        };

        var employeeDepartmentInfo = departments.Join(
            employees,
            department => department.Id,        // Outer key selector
            employee => employee.DepartmentId, // Inner key selector
            (department, employee) => new       // Result selector
            {
                EmployeeName = employee.Name,
                DepartmentName = department.Name
            });

        Console.WriteLine("Employees and their Departments:");
        foreach (var item in employeeDepartmentInfo)
        {
            Console.WriteLine($"- {item.EmployeeName} is in {item.DepartmentName}");
        }
    }
}

Output:

Employees and their Departments:
- Bob is in HR
- Alice is in Engineering
- Charlie is in Engineering
- David is in Sales
- Eve is in Engineering