C# – LINQ Join Examples

Join is a LINQ functionality to combine two collections and produce a single result set. Connection happens by comparing items from both series. When there is a match then such pair is one of the output elements.

Let’s consider following example. We’ve got two separate collections: countries and cities, which store objects of Country and City class. Code definition of these classes is attached below. As you can see both of them are very similar, however City contains one more property which is identifier of its parent – CountryId – which purpose is to store information about a country it depends to.

For those of you who are familiar with SQL, we could name CountryId as an equivalent of foreign key, known from relational databases.

Now, let’s define mentioned earlier collections and fulfil them with sample data. Lack of Japan’s cities is intentional to show how Join functionality behaves when there is no match between two lists.

Our goal is to list cities with its country names. To achieve it we’ll use Join function provided by LINQ. We will present it in two available expression forms: Lambda and Query.

Lambda expression

Join function is called on cities collection. First argument is countries collection or saying more general, it’s the other collection to connect with. Second and third arguments of Join are selectors which will be used to link elements from separate sets. In our case a pair is created when CountryId from city object equals CountryId from country object. Fourth argument is result selector where we can define the structure of returned data.

Result can be displayed with simple foreach loop.

Now, switch the query, so that Join function is called on countries collection and cities list is passed as first argument.

When we print it, a result we see is exactly the same. As you can notice Japan is still not part of the output. The reason is Join function returns only matched items, whilst our sample data doesn’t contain any Japan’s city, as a result of what there was no match. To sum up, Join behaves like inner join from SQL.

Query expression

The other way we can use Join functionality is query expression. This notation is more like SQL, so might be more readable for some of you. Functionality wise it’s the same as Lambda expression. In the first two lines we define collections to query on and join. Third line specifies selectors and fourth line onwards is a definition of output data.

Displaying result same way as before gives us the same list of cities and its countries.