HomeSearch

C# Join: LINQ Keyword and Extension Method

Use the join keyword in query expressions. Include the System.Linq namespace.

Join.

This is a keyword in LINQ. As with other query languages (such as SQL) joining matches every element in two collections based on some condition.

Queries.

We use this keyword in a query expression (beginning with from). We create new data structures (projections) based on the contents of elements.

First example.

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

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 Join,

we provide delegates (lambdas) as arguments. These are clauses in a query. Both examples join ints1 with ints2. They select elements in ints1 that exist 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

Syntax: In my view, the query expression is easier to read. This would make it more maintainable and less likely to create bugs.

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

C# program that uses Join 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

Example 2.

This example program uses two classes for storing data. Customer has an ID and a Name for each instance. And Order has an ID and a Product string for each instance.

Info: In the query expression, the customers array is used and each element from that array is identified as "c".

And: The orders array is also used, and each element from that is identified as "o".

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

SQL: This syntax is basically the same as in SQL. Occasionally it is easier to develop logic in this style of language.

C# program that uses join and equals in query 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

GroupJoin.

Join is different from GroupJoin. With Join, we cannot create a new type to store multiple results together in a single element.

And: We can only select a single value. But GroupJoin is invoked with the join query expression keyword.

GroupJoin

Fluent syntax, join IDs.

This example joins two arrays of elements on the ID property of each element. It uses Animal and Medication instances.

So: A cat with a specific ID may have 2 medications prescribed to it. The Join call resolves all of these.

And: We use the Join() method with lambda expression arguments. This is equivalent a query expression with the "join" clause.

C# program that uses Join, lambda expressions using System; using System.Linq; class Animal { public int ID { get; set; } public string Breed { get; set; } } class Medication { public int ID { get; set; } public string Type { get; set; } } class Program { static void Main() { // Example animals in veterinarian office. var animals = new Animal[] { new Animal{ID = 0, Breed = "cat"}, new Animal{ID = 10, Breed = "dog"} }; // Example medications (prescriptions). var medications = new Medication[] { new Medication{ID = 10, Type = "antibiotic"}, new Medication{ID = 0, Type = "sedative"}, new Medication{ID = 0, Type = "antihistimine"} }; // Use fluent join syntax on ID. var query = animals.Join(medications, a => a.ID, m => m.ID, (a, m) => new { a.Breed, m.Type }); // Results. foreach (var group in query) { Console.WriteLine($"{group.Breed} prescribed {group.Type}"); } } } Output cat prescribed sedative cat prescribed antihistimine dog prescribed antibiotic

String.Join.

The "join" keyword in LINQ is not related to the string.Join method, which combines an array or List of strings into one string. Thread.Join is also a different thing.string.JoinThread.Join

Specification.

Part of this article is based on the C# specification. In the specification, detailed examples are given for how query expressions are processed.

And: This is near the end of the horrifying 143-page chapter on expressions. Thoroughness is helpful in language specifications.

Note: Thanks to Rob Martin for suggesting the Join() fluent syntax example. Two lambda expressions must be used.

A summary.

Using the LINQ extensions in the C# language, we can implement join expressions. This can make some matching routines more concise in a program.

It can help us

convert SQL logic to C# code in some cases as well. The Join extension method can be directly used. But this complicates syntax due to its use of 3 delegate methods.Delegates
Home
Dot Net Perls
© 2007-2019 Sam Allen. All rights reserved. Written by Sam Allen, info@dotnetperls.com.