C# Join

Join objects together

LINQ provides a fully featured query language. It offers the join operation. As with other query languages—such as SQL—joining matches every element in two collections based on some condition.

Example

Squares: abstract

This first example shows the Join extension method from the System.Linq namespace. And then it shows the equivalent join query expression syntax. Internally the join query is translated to the Join() extension method by the C# compiler.

Extension Method

Tip:You can read in painful detail how query expressions are translated in the chapter on Expressions (7) in the C# specification.

But:This material is complex, tiresome and not all that useful for actual development.

With the Join method, we provide delegates as arguments. With the query expression, we specify this in a clause. Both of these examples join ints1 with ints2. They select every element in ints1 that exists in ints2 with an added 1.

So:If ints1 contains an element of value 4, it is selected only if there is an element of value of 5 in ints2.

Int Array
Program that uses Join: C#

using System;
using System.Linq;

class Program
{
    static void Main()
    {
	// Array 1.
	var ints1 = new int[3];
	ints1[0] = 4;
	ints1[1] = 3;
	ints1[2] = 0;

	// Array 2.
	var ints2 = new int[3];
	ints2[0] = 5;
	ints2[1] = 4;
	ints2[2] = 2;

	{
	    // Join with method call.
	    var result = ints1.Join<int, int, int, int>(ints2,
		x => x + 1,
		y => y,
		(x, y) => x);

	    // Display results.
	    foreach (var r in result)
	    {
		Console.WriteLine(r);
	    }
	}

	{
	    // Join with query expression.
	    var result = from t in ints1
			 join x in ints2 on (t + 1) equals x
			 select t;

	    // Display results.
	    foreach (var r in result)
	    {
		Console.WriteLine(r);
	    }
	}
    }
}

Output

4  (First loop)
3
4  (Second loop)
3
Programming tip

In my view, the second syntax in the example—with the query expression—is easier to read. This would make it more maintainable and less likely to create bugs. Code that is easier to read is often better.

Tip:The Join and GroupJoin methods are hard to use directly. They are best used indirectly, through the query syntax.

Example 2

Note

This example program uses two classes for storing data. It uses the Customer class, which has an ID and a Name for each instance, and the Order class, which has an ID and a Product string for each instance.

And:In the Main method, we use the abbreviated C# syntax for constructing the array instances. Each has four elements.

Finally:The query expression uses the join keyword to create new objects where the ID equals.

Program that uses join and equals in query: C#

using System;
using System.Linq;

class Customer
{
    public int ID { get; set; }
    public string Name { get; set; }
}

class Order
{
    public int ID { get; set; }
    public string Product { get; set; }
}

class Program
{
    static void Main()
    {
	// Example customers.
	var customers = new Customer[]
	{
	    new Customer{ID = 5, Name = "Sam"},
	    new Customer{ID = 6, Name = "Dave"},
	    new Customer{ID = 7, Name = "Julia"},
	    new Customer{ID = 8, Name = "Sue"}
	};

	// Example orders.
	var orders = new Order[]
	{
	    new Order{ID = 5, Product = "Book"},
	    new Order{ID = 6, Product = "Game"},
	    new Order{ID = 7, Product = "Computer"},
	    new Order{ID = 8, Product = "Shirt"}
	};

	// Join on the ID properties.
	var query = from c in customers
		    join o in orders on c.ID equals o.ID
		    select new { c.Name, o.Product };

	// Display joined groups.
	foreach (var group in query)
	{
	    Console.WriteLine("{0} bought {1}", group.Name, group.Product);
	}
    }
}

Output

Sam bought Book
Dave bought Game
Julia bought Computer
Sue bought Shirt
Question and answer

In the query expression, the customers array is used and each element from that array is identified as "c". The orders array is also used, and each element from that is identified as "o".

And:The join takes the ID property from "c" and "o" and matches them. As the matches occur, new elements are created in the result.

Same as SQL. This syntax is basically the same as in SQL. Occasionally it can be easier to develop logic in this style of language. Unfortunately, using an imperative, low-level approach is likely faster in the C# language.

For Loop: Imperative

Discussion

Programming tip

Join is different from GroupJoin. With Join, we cannot create a new type to store multiple results together in a single element. We can only select a single value. But GroupJoin is invoked with the join query expression keyword.

GroupJoin MethodThe C# Programming Language: C-Sharp

Part of this article is based on the C# specification. In the specification, detailed examples are given for how query expressions are processed. This is near the end of the horrifying 143-page chapter on expressions—see page 333.

Note:Please remember that thoroughness is a valuable attribute for language specifications.

Specification

Summary

Logo

Using the LINQ extensions in the C# language, you can implement join expressions. This can make some matching routines more concise in your programs. It can help you convert SQL logic to C# code in some cases as well.

Also:The Join extension method can be directly used. But this complicates syntax due to its use of three delegate methods.

Delegate TypesLambda Expression

C#: LINQ