C# LINQ,
Tags: codenewbie, csharp, tutorial, beginners
Published: 2023-05-22 22:11:48

LINQ - (Language Integrated Query) is an absolute gem of a tool available in C#. It works the same as SQL does and allows you to perform querys on objects within your code. 

This can be done in two ways. You can use the language-level query syntax, or the LINQ API. 

### Linq Api - Language Level Query Syntax 

You may see in code something that resembles a SQL, like this :

```csharp
var animals = new List<Animal>{ new Animal{Name="Dog", Age= 2, Sound="Bark"},
new Animal{Name="Cat", Age=2, Sound="Meow",
new Animal{Name: Fox, Age=5, Sound="Bark"}

var barkingAnimals = 
   from animal in animals
   where animal.Sound == "Bark"
   select animal. 
```

You can build a query just like you would with other query languages such as **SQL**. This query language can be useful for building complex queries, but in this example it could be deemed excessive. We can simplify this select statement using the **_LINQ API methods_**

## Linq API - Method Syntax

The LINQ API methods utilises a predicate (in the form of a lambda extension) to determine the criteria, (you can learn about these in my previous [module](https://dev.to/gweaths/c-lambda-expressions-lambda-operator-40kd). 

So let's look at how we could re-write 

```c#
const barkingAnimals = animals.Where(x=> x.Sound == "Bark").ToLis();
```

It's a lot easier to write and much more concise for such a simple filter. 

I find it reads a lot better too, 
> "barking Animals equals all the animals where the sound property equals Bark"

### Why do we add `ToList()` on the end?

Linq querying methods all returns an `IQueryable` object. This informs the compiler that the variable is not the result of the query, but the definition of the query, see [deferred execution](#deferred-execution) later in this article.

In order to be able to use the results of the query we can either:
- iterate over the queryable object (e.g using a ForEach loop)

- convert to an IEnunerable type, e.g a List / Array. 

### Common LINQ API methods

### OrderBy

OrderBy is a very useful LINQ Api method which simply allows us to order any object that inherits from IEnumerable, for example Lists or Arrays. 

We can use it like so:

```csharp

var orderedByAge = people.OrderBy(x=>x.Age);

// or

var orderedByAgeDescending = people.OrderByDescending(x=>x.Age);
```
the above shows examples of ordering by Age in both ascending and descending order. 

### First()
```c#
var first = animals.First(x=> x.Sound == "Bark");
```

This will return the first object from the list that matches the criteria.  

### Single / SingleOrDefault

This is used when you know there will only ever be / or you expect there only to be **one** object that matches your criteria. 

Example :
```c#
var cat = animals.Single(x=>x.Name == "Cat");
```

However, we all know that data can change over time, or 3rd party services could return different data than what was expected. It is always best to write defensive code where possible. 

If we were to call the above code, and it finds there are actually more than one object with the name "Cat", it would throw an uncaught error (this means we're not expecting nor handling the error correctly).

To prevent this, we can use the `SingleOrDefault` method. This method will handle the error for us, and return the default value on error , so therefore `cat` would equal `null` because the default value for a string is `null`. We can then check within the code that the cat variable is not null:

```csharp
var cat = animals.SingleOrDefault(x=> x.Name=="Cat");

if(cat != null){
  Console.WriteLine("A single cat was found");
}

I will teach how to handle errors, in another article.

```

## Select

Say we wish to return only the types of animal,i.e we don't need all the other information.

If so we can use the `Select` method. This will create a new object for each element in the list / array. 

Example:

```csharp 
var typesOfAnimal = animals.Select(x=>x.Name).ToList();
```
But suppose we want to have the name and there sound? That's just as easy with the Select method, however this time we'll create an anonymous object instead of just returning the property. 

```csharp
var animals = animals.Select(x=> { Name = x.Name, 
Noise = x.Sound}).ToList();
```
You can see a full list of available methods on the Microsoft site.

## Combining methods

Another filtering extension method which is available on the IEnumerable types is the `Contains` method. This method does exactly what you'd expect, it returns all the items which contain the given predicate. 

For example, say we have a list of People. And we want to find all the people who's address contains "_United Kingdom_".


```csharp

var people = new List<People>(){
  {Name:"John Doe", Address:"123 Privet Drive, Hogwarts, United Kingdom"},
  {Name:"Alex the Kidd", Address: "Rock Paper Scissors Avenue, United Kingdom"},
  {Name: "Donkey Kong", Address:" The Monkey Temple, Jungle"}
}
```

We could utilise a combination of the `.Where()` and the `Contains()` to achieve this like below:

```csharp

var ukResidents = peopleList.Where(p => p.Address.Contains("United Kingdom")).ToList();

var ukResidents = people.

```

## Deferred Execution

LINQ queries use what's called deferred execution, meaning that the query is not executed immediately when it is defined.

Instead, it is executed when the query results are iterated or when certain operators trigger the execution explicitly. This deferred execution enables optimisations and improves performance by avoiding unnecessary computations.

This goes back to what I discussed earlier with the conversion  of IQueryable to, for example a List using `.ToList()`. It's the to list that converts it to a list and executes the query.

Lets take a look at an example:

```csharp

//first declare a list of people again
var people = new List<People>(){
  {Name:"John Doe", Address:"123 Privet Drive, Hogwarts, United Kingdom"},
  {Name:"Alex the Kidd", Address: "Rock Paper Scissors Avenue, United Kingdom"},
  {Name: "Donkey Kong", Address:" The Monkey Temple, Jungle"}
}

// then we'll define the query
var peopleCalledJohnQuery = people.Where(x=>x.Name == "John");

// this will create the query object, and if you hover over peopleCalledJohnQuery
// intellisense will inform you that the variable is of type _IQueryable_

Console.WriteLine("Just log out something random");

// now convert the IQueryable query object to a List, thus invoking the actual query.

var list = peopleCalledJohnQuery.ToList();

```
Although a very basic example, this example illustrates you can create a queryable object, execute more code, before actually executing why look the query by running the `.ToList()` extension method. 


## Chaining IQueryable Api methods

Like the combining of _Where_ and _Contains_ we used earlier. You can go one step further by Chaining LINQ API methods. 

Let's take the `Where()`, and `GroupBy()` methods. 

This would allow us to filter some of the data, and then group the data by a property. 

So let's put everything we've learnt within this article to use, and chain the two methods. 

However instead of creating a new variable using the `.ToList()` method to execute and give us a list of results we can just utilise the query object within a ForEach loop, this will execute the query and allow us to loop over the results at the same time.

 
```csharp
using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main()
    {
        List<Person> people = new List<Person>
        {
            new Person { Name = "John", Age = 30 },
            new Person { Name = "Alice", Age = 25 },
            new Person { Name = "Bob", Age = 30 },
            new Person { Name = "Charlie", Age = 25 },
            new Person { Name = "Eve", Age = 35 }
        };
        
        var groupedPeople = people
            .Where(p => p.Age >= 30)  // Filter people with age >= 30
            .GroupBy(p => p.Age);    // Group people by their age
        
        foreach (var group in groupedPeople)
        {
            Console.WriteLine($"Age Group: {group.Key}");
            foreach (var person in group)
            {
                Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
            }
            Console.WriteLine();
        }
    }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
```
And there you have it, a brief introduction to C# LINQ. Have a play around and see what you can achieve with this powerful tool. 

You can find some useful examples on the Microsoft website [here](https://learn.microsoft.com/en-us/dotnet/csharp/tutorials/working-with-linq)

Feel free to give me a follow here and on [Twitter](http://twitter.com/gweaths) for updates on new articles, or to ask any questions.