An Introduction to LINQ

An Introduction to LINQ

How to easily filter through lists with .NET

Hi lovely readers,

If you ever worked with data in the back-end you probably used lists or other collection types before. Getting the data or elements you need from those collections can sometimes be a difficult task, especially if the collection is very big.

C# has a set of extensions that help you write queries. These queries make it easier to filter, select or group the data you need. This set of extensions is collectively called LINQ (Language Integrated Query). Learning how to work with LINQ can be difficult but once you’re good at it, working with data in lists becomes way and way easier.

Lets talk about some examples that are great for beginners that can really help you.

Query syntax or Method syntax

Before we start you have to know that there are two different ways to write LINQ syntax. What you want to use it’s up to you.

There’s query syntax that looks similar to SQL queries, and there is method syntax that’s similar to how you write lambda queries in other backend languages. Let me show you.

Query syntax

//QUERY SYNTAX

//making a new list
List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

//filter list
var longAnimalNames = from name in animalNameList
                                        where name.Length >= 5
                                        select name;

This syntax returns all the names that have more than, or are equal to 5 letters. If you already know some SQL, you can tell that is similar to what you’re used there.

The biggest advantage of using Query syntax is that a lot of people find it very readable, and easier to remember. The biggest disadvantage is that LINQ doesn’t allow every method to be used in query syntax. It will sometimes force you to use method syntax instead.

Method syntax

//METHOD SYNTAX

//making a new list
List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

//filter list
var longAnimalNames = animalNameList.Where(name => name.Length >= 5);

This syntax, just like the query syntax example, returns all the names that have more than, or are equal to 5 letters. This syntax might be easier if you’re already used to writing lambda queries with Python, Java, or any other backend language.

The advantages are that method syntax looks more like normal C# code. And, you can use every single method available to LINQ. The disadvantage is that, to some, it might be harder to read than query syntax.

Single element methods

These are queries with which you can get one single element out of a list. Keep in mind that if the LINQ query can’t find a element, it will throw an exception. Be sure there is an element that fits the query or use a try - catch block if you’re going to use this in your own code.

ElementAt() method

The ElementAt() method returns the element that’s sitting at the int value you give in the parameter. Here’s an example:

List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

var animalName = animalNameList.ElementAt(2);

Console.WriteLine(animalName); //prints 'Donut'

Keep in mind that collections always start at 0, so if you put ElementAt(2) it will return Donut.

First() method

The first() method returns the element that’s at the very beginning of the list. Here’s an example:

List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

var animalName = animalNameList.First();

Console.WriteLine(animalName); //prints 'Boy'

Last() method

The last() method returns the element at the very end of the list. Here’s an example:

List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

var animalName = animalNameList.Last();

Console.WriteLine(animalName); //prints 'Tebby'

Multiple elements methods

If you want a group of elements instead of just one element, there are methods for that too.

Where() method

The Where() method is used a lot of times and is used for filtering for all kinds of values you need. This can be filtering with conditions or filtering on exact values.

Contains() method

List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

var animalNames = animalNameList.Where(name => name.ToLower().Contains('d'));

foreach (string name in animalNames)
{
    Console.WriteLine(name); //prints 'Donut' and 'Cody'
}

All the strings that contain the letter d in the list will be stored in the animalNames collection. First, we change every string to only have lowercase letters, and then we look for the letter.

We can also do this in query syntax:

List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

var animalNames = from name in animalNameList
                  where name.ToLower().Contains('d')
                  select name;

foreach (string name in animalNames)
{
    Console.WriteLine(name); //prints 'Donut' and 'Cody'
}

Conditional filtering

You can also filter based on a value that should be true. For example, every name that’s equal to or longer than 5 letters:

List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

var longAnimalNames = animalNameList.Where(name => name.Length >= 5);

foreach (string name in longAnimalNames)
{
    Console.WriteLine(name); //prints 'Donut' and 'Tebby'
}

And, once again, it works in query syntax as well if that’s what you prefer:

List<string> animalNameList = new(){"Boy", "Goku", "Donut", "Cody", "Tebby"};

var longAnimalNames = from name in animalNameList
                                        where name.Length >= 5
                                        select name;

foreach (string name in longAnimalNames)
{
    Console.WriteLine(name); //prints 'Donut' and 'Tebby'
}

Filtering with numeric lists

Can you also filter integer- or double-value lists? Yes, you can. It works the exact same as string lists. Here are some code snippet examples, once again:

List<int> numberList = new() {1, 2, 3, 3, 4, 5, 3, 2, 3, 4};

var numberResult = numberList.Where(number => number is 4 or 2);

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 2,4,2,4
}

In this query we look through the numberList and store the elements that are either 4 or 2 in the numberResult collection.

and also conditional filtering is an option:

List<int> numberList = new() {1, 2, 3, 3, 4, 5, 3, 2, 3, 4};

var numberResult = numberList.Where(number => number > 3);

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 4,5,4
}

In this query we put all the elements of integers that are higher than 3 in the collection numberResult.

And of course, we can use both of these examples in query syntax as well!

List<int> numberList = new() {1, 2, 3, 3, 4, 5, 3, 2, 3, 4};

var numberResult = from number in numberList
                   where number is 4 or 2
                   select number;

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 2,4,2,4
}
List<int> numberList = new() {1, 2, 3, 3, 4, 5, 3, 2, 3, 4};

var numberResult = from number in numberList
                   where number > 3
                   select number;

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 4,5,4
}

OrderBy() and OrderByDescending()

Having collections with 2,4,2,4 in it can be quite unhelpful. Sometimes you want to order it and that’s possible. Here’s an example:

List<int> numberList = new(){1, 3, 5, 3, 4, 2};

var numberResult = numberList.OrderBy(number => number);

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 1,2,3,3,4,5
}

This query puts the numberList in order from lowest value to highest. If you want to it from highest to lowest value you can use OrderByDescending() instead:

List<int> numberList = new(){1, 3, 5, 3, 4, 2};

var numberResult = numberList.OrderByDescending(number => number);

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 5,4,3,3,2,1
}

You can order the list with query syntax:

List<int> numberList = new(){1, 3, 5, 3, 4, 2};

var numberResult = from number in numberList
                   orderby number
                   select number;

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 1,2,3,3,4,5
}

Where() and OrderBy() method

If you need to, you can use the Where() and OrderBy() together to get even better results. Look at this example:

List<int> numberList = new(){1, 3, 5, 3, 4, 2};

var numberResult = numberList.OrderBy(number => number).Where(number => number > 2);

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 1,2,3,3,4,5
}

And, of course, in query syntax:

List<int> numberList = new(){1, 3, 5, 3, 4, 2};

var numberResult = from number in numberList
                   where number > 2
                                     orderby number
                   select number;

foreach (int number in numberResult)
{
    Console.WriteLine(number); //prints 3,3,4,5
}

Boolean methods

Sometimes it can be useful to just know if a list contains something or not, that’s it. So there are methods that give you back a true or false.

Any() method

You can use the Any() method to figure out if there is any element that fits your query. If there is an element (or multiple elements) it will return true:

List<int> numberList = new() {1, 3, 5, 3, 4, 2};

var numberResult = numberList.Any(number => number >= 4);

Console.WriteLine(numberResult);//prints true

Because there’s a 4 and a 5 in the list, the result will be true.

All() method

You can use the All() method to figure out if all elements in the list fits your query. If all the elements fit the query, it will return true:

List<int> numberList = new() {1, 3, 5, 3, 4, 2};

var numberResult = numberList.All(number => number > 0);

Console.WriteLine(numberResult);//prints true

Numeric methods

There are some methods that I don’t exactly know where to put but are still helpful. Here they are

Sum() method

The Sum() method sums up all the values in a numeric list.

List<int> numberList = new() {1, 3, 5, 3, 4, 2};

var numberResult = numberList.All(number => number > 0);

Console.WriteLine(numberResult);//prints 18

Count() method

The Count() method counts up all the elements

List<int> numberList = new() {1, 3, 5, 3, 4, 2};

var numberResult = numberList.Count();

Console.WriteLine(numberResult);//prints 6

Min() method

The Min() method returns the lowest value in a list.

List<int> numberList = new() {1, 3, 5, 3, 4, 2};

var numberResult = numberList.Min();

Console.WriteLine(numberResult);//prints 1

Max() method

The Max() method returns the highest value in a list.

List<int> numberList = new() {1, 3, 5, 3, 4, 2};

var numberResult = numberList.Max();

Console.WriteLine(numberResult);//prints 5

That’s a wrap!

Thank you for reading. I hope this can help you in your (future) career as a .NET or C# developer. If you have any suggestions or tips, feel free to leave a comment or contact me on Twitter at @lovelacecoding. See you later!