DEV Community

Cover image for A quick guide to LINQ with examples
Cesar Aguirre
Cesar Aguirre

Posted on • Updated on • Originally published at canro91.github.io

A quick guide to LINQ with examples

I originally posted an extended version of this on my blog. It's part of a series about LINQ and other C# features.

Today a friend asked me about LINQ. I guess she was studying for a technical interview. So, dear Alice, this is what LINQ is and these are the most common LINQ methods with examples in C#.

Language-Integrated Query (LINQ) is the declarative way of working with collections in C#. LINQ works with databases and xml files, too. The most common LINQ methods are: Where, Select, Any GroupBy and FirstOrDefault. LINQ has an API syntax, extensions methods on the IEnumerable type, and a query syntax, a SQL-like syntax.

1. LINQ is declarative

LINQ is declarative. It means you write your code stating the results you want, instead of doing every step to get those results.

With LINQ, you write code to "filter a collection based on a condition". Instead of writing code to "grab an element, check if it satisfies a condition, then move to the next element, check again...", etc.

LINQ is a better alternative to query collections using for, foreach or any other loop. Because, with LINQ you can write more expressive and compact code.

Waiting at a cinema before a movie starts

Photo by Erik Witsoe on Unsplash

Our first example: Movies

Let's see an example. Let's start with the collection of movies we have watched. We have a Movie class with a name, release year and rating. Let's find our favorite movies, the ones with rating greater than 4.5.

This is a console program to print our favorite movies. Let's use records and top-level statements from recent C# versions.

var movies = new List<Movie>
{
    new Movie("Titanic", 1998, 4.5f),
    new Movie("The Fifth Element", 1997, 4.6f),
    new Movie("Terminator 2", 1991, 4.7f),
    new Movie("Avatar", 2009, 5),
    new Movie("Platoon", 1986, 4),
    new Movie("My Neighbor Totoro", 1988, 5)
};

var favorites = new List<Movie>();
foreach (var movie in movies)
{
    if (movie.Rating > 4.5)
    {
        favorites.Add(movie);
    }
}

foreach (var favorite in favorites)
{
    Console.WriteLine($"{favorite.Name}: [{favorite.Rating}]");
}

Console.ReadKey();

record Movie(string Name, int ReleaseYear, float Rating);
Enter fullscreen mode Exit fullscreen mode

Notice the foreach loop and the comparison using an if statement to look for ratings greater than 4.5.

For our sample movies, the above program will print the next four movies.

The Fifth Element: [4.6]
Terminator 2: [4.7]
Avatar: [5]
My Neighbor Totoro: [5]
Enter fullscreen mode Exit fullscreen mode

Change the example to use your own movies and see which ones are your favorites!

Our first LINQ method: Where

LINQ methods are extension methods on the IEnumerable type. This type represents objects we can loop through. Like, arrays, lists, dictionaries, among others.

To work with LINQ, you need to be comfortable with delegates and lambda functions. A delegate is a reference to a method. And, a lambda function is a method with only the parameters and the body.

Now, to the actual example. We want to filter our list of movies to keep only the ones with rating greater than 4.5. The LINQ method to filter collections is Where.

The LINQ Where method returns a new collection with all the elements that meet a condition.

Let's replace the foreach statement from our first example with the Where method. And, let's use the condition inside the if statement as the filter condition for the Where method. Our example looks like this:

var movies = new List<Movie>
{
    new Movie("Titanic", 1998, 4.5f),
    new Movie("The Fifth Element", 1995, 4.6f),
    new Movie("Terminator 2", 1999, 4.7f),
    new Movie("Avatar", 2010, 5),
    new Movie("Platoon", 1986, 4),
    new Movie("My Neighbor Totoro", 1988, 5)
};

var favorites = movies.Where(movie => movie.Rating > 4.5);
foreach (var favorite in favorites)
{
    Console.WriteLine($"{favorite.Name}: [{favorite.Rating}]");
}

Console.ReadKey();

record Movie(string Name, int ReleaseYear, float Rating);
Enter fullscreen mode Exit fullscreen mode

We replaced the foreach and if statements with a single line of code:

var favorites = movies.Where(movie => movie.Rating > 4.5);
Enter fullscreen mode Exit fullscreen mode

More compact, isn't it? Also, we turned the condition inside the if statement into a lambda function. Instead of lambda functions, you could use private methods too.

LINQ methods don't change the original collection. They return a result without modifying the original collection. From our example, when we used the Where method, it returned a new collection. It didn't remove any elements from the original movies list.

2. Most common LINQ methods

So far, we have seen only one LINQ method, Where. Let's see other common methods.

1. Select

With Select, you can transform every element of a collection. It applies a function on every element.

Let's find only the names of our favorite movies.

var favorites = movies.Where(movie => movie.Rating > 4.5)
                      .Select(movie => movie.Name);

foreach (var name in favorites)
{
    Console.WriteLine(name);
}

// The Fifth Element
// Terminator 2
// Avatar
// My Neighbor Totoro
Enter fullscreen mode Exit fullscreen mode

Notice, how this time we have nested two LINQ methods. The result from Where will be the input of Select.

For more readability, we often align the nested LINQ methods vertically by the (.) dot.

2. Any

The Any method check if a collection is empty. Also, it checks if a collection has at least one element matching a condition. It returns either true or false. It doesn't return a new collection.

Let's see if we have watched movies with a low rating.

var hasAnyMovies = movies.Any();
// true

var hasBadMovies = movies.Any(movie => movie.Rating < 2);
// false
Enter fullscreen mode Exit fullscreen mode

3. GroupBy

GroupBy groups the elements of a collection based on a key. It returns a collection of "groups" or "buckets" organized by a key.

Let's group our movies by rating.

var groupedByRating = movies.GroupBy(movie => movie.Rating);

foreach (var group in groupedByRating)
{
    Console.WriteLine($"Rating: {group.Key}");

    foreach (var movie in group)
    {
        Console.WriteLine($"{movie.Name}");
    }
    Console.WriteLine();
}
Enter fullscreen mode Exit fullscreen mode

This will be the output.

Rating: 4.5
Titanic

Rating: 4.6
The Fifth Element

Rating: 4.7
Terminator 2

Rating: 5
Avatar
My Neighbor Totoro

Rating: 4
Platoon
Enter fullscreen mode Exit fullscreen mode

Also, GroupBy allows you to transform each group. This time, let's count the movies with the same rating.

var groupedByRating = movies.GroupBy(movie => movie.Rating,
                                    (rating, movies) => new { Rating = rating, Count = movies.Count() });

foreach (var group in groupedByRating)
{
    Console.WriteLine($"{group.Rating}: [{group.Count}]");
}
Enter fullscreen mode Exit fullscreen mode

Notice the second parameter of the GroupBy. It's a Func with the key and the elements of each group. We also used an anonymous object new { Rating=..., Count=... }. It's like a regular object, but we didn't specify a name.

And this is the output of counting movies by rating.

4.5: [1]
4.6: [1]
4.7: [1]
5: [2]
4: [1]
Enter fullscreen mode Exit fullscreen mode

4. First and FirstOrDefault

First and FirstOrDefault return the first element in a collection. First throws an exception if the collection is empty. Unlike First, FirstOrDefault returns a default value if the collection is empty.

Also, First and FirstOrDefault return the first element matching a condition.

Let's find the oldest movie we have watched.

var oldest = movies.OrderBy(movie => movie.ReleaseYear)
                   .First();

// Platoon
Enter fullscreen mode Exit fullscreen mode

This time, we used the OrderBy to sort the movies collection by release year. To then, grab the first one. Two examples for the price of one!

In the same spirit of First and FirstOrDefault, you have Last and LastOrDefault. But, they return the last element instead of the first one.

3. Cheatsheet

There are more LINQ methods than the ones we've seen so far. These are some of them.

Method Function
Where Filter a collection
Select Transform every element of a collection
Any Check if a collection is empty
Count Count all elements of a collection
Distinct Find the unique elements of a collection
GroupBy Group the elements of a collection based on a key
OrderBy Sort a collection based on a key
First Find the first element of a collection. Throw if the collection is empty
FirstOrDefault Same as First, but it returns a default value if it's empty
Last Find the last element of a collection. Throw if the collection is empty
LastOrDefault It returns a default value if it's empty, instead
Single Find only one element in a collection matching a condition. Throw, otherwise
SingleOrDefault It returns a default value if there isn't one matching element, instead
Take Pick the first n consecutive elements of a collection
TakeWhile Pick the first consecutive elements that satisfy a condition
Skip Return a collection without the first n consecutive elements
SkipWhile Return a collection without the first consecutive elements that satisfy a condition
Sum Sum the elements of a collection
Min, Max Find the smallest and largest element of a collection
ToDictionary Convert a collection into a dictionary

Voilà! That's it, Alice. That's all you need to know to start working with LINQ in your code in less than 15 minutes. With LINQ you can write more compact and expressive code. The next time you need to write logic using loops, give LINQ a try!

To learn more about LINQ, check an extended version of this post on my blog. Also, take a look at my C# Definitive Guide.

Hey! I'm Cesar, a software engineer and lifelong learner. Visit my blog to learn more about my work! If you want to support my work, check my Getting Started with LINQ course on Educative.

Happy LINQ time!

Discussion (0)