Break the LINQ - Dissecting the "Where" of LINQ
Tags: dotnet, csharp
Published: 2020-03-27 19:25:41

I have been a .net developer for quite some time now and there are things which I have just blindly implemented by referring to code snippets without caring about their underlying intricacies, one of them being LINQ. I’m sure we all know what it stands for and why it is used so I won’t be going there.  What I really want to discuss here is the LINQ fluent functions which we use on a family of `IEnumerables`. 
I always felt lazy to write these queries on my own and would always turn to online examples. I never bothered to look at the overloads and understand them. No more.Here is my very first attempt at writing a post.
To write a LINQ query efficiently there are three things you must be aware of
1.	Delegates
2.	Lambda Expressions
3.	variety of extension methods offered on the *Enumerable* class

I would like to limit this post to dissect the most commonly used "Where" extension method. The documentation for it as below
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/vl71euk9r5bx7ta8e23w.JPG)

The first parameter preceded by *"this"* keyword tells us right there itself that it is an extension method. Also notice that it returns an `IEnumerable<TSource>`. So *Where* is an extension method on a collection which is of type `IEnumerable<TSource>` which also returns an `IEnumerable<TSource>`. The collection referred here could be any collection which implements the IEnumerable interface e.g. List<TSource>, IList<TSource>.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o0din5w99x0xu9x7na1f.JPG)

We move to the second parameter of the method `Func<TSource,bool> predicate`. **Func** is a built-in delegate in .NET. 

Delegate is a type to represent a method signature. E.g. if we have a method
 ```public string FormatNumber(int number)```
 then we would write its “delegate” type as 
```public delegate string FormatNumberDelegate(int number)```

Here the ***FormatNumberDelegate*** is a type that would represent the method ***FormatNumber*** or any method which accepts an integer and returns a string. If we were to represent this as *Func* then the resultant delegate would be
`Func<int,string>` i.e. "Func" is any method which takes in an **integer** parameter and returns a **string**.

Going back to our *Where* extension, `Func<TSource,bool>` represents any method which takes in a parameter of `TSource` and returns a boolean. The boolean returned is essentially the condition which we would like to evaluate. If from a list of Employees, we want to filter the female employees, then we would write a condition which evaluates to true (a boolean) when the employee is a female. 



Lets say we have a class `Employee` as follows
```cs
public class Employee
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Designation { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public Gender Gender { get; set; }
    }

 public enum Gender
    {
        F,
        M
    }
```

so our condition would be 
`if(employee.Gender == Gender.F) return true;`

The simplest way to write this is
```cs
bool FilterFemaleEmployees(Employee employee)
        {
            if (employee.Gender == Gender.F)
                return true;
            return false;
        }
```

and then we can use it with our *Where* extension as `var femaleEmployees = employees.Where(FilterFemaleEmployees);`

Comparing this with the documentation for the *Where* extension,
*TSource* = Employee
`IEnumerable<TSource>` = `var femaleEmployees is IEnumerable<Employee>` which is returned by the *Where* method
`Func<TSource,bool>` = `bool FilterFemaleEmployees(Employee employee)`

Lets take it to one level up by making use of anonymous delegate. 

The FilterFemaleEmployees is a ***named*** delegate which is good but while using LINQ the main focus is on compact queries , writing efficient code with as few lines as possible.
With an anonymous delegate, the query would look like
```cs 
var femaleEmployees = employees.Where(delegate (Employee employee)
            {
                if (employee.Gender == Gender.F)
                    return true;
                return false;
            });
```
whenever we are evaluating a condition, its result is going to return a boolean. i.e if we just return employee.Gender == Gender.F , it is going to return a true or a false based on the value of employee.Gender. So reducing the code further,

```cs
var femaleEmployees = employees.Where(delegate (Employee employee)
            {
                return employee.Gender == Gender.F;
            });
```

Now comes the lambda ! Lambdas are a great way to represent an anonymous function. There are three parts to a lambda expression :
the parameters, the => operator and the method body (statement or expressions).
We remove the delegate keyword and replace it with the following
```cs
 var femaleEmployees = employees.Where( (Employee employee)=>
            {
                return employee.Gender == Gender.F;
            });
```
Another good feature of a lambda is the parameter inference. In the above, we are supplying a parameter of type Employee to the anonymous function. But here we can make good use of the parameter inference and let the compiler figure out its type (another step towards compact code)
```cs
 var femaleEmployees = employees.Where( (employee)=>
            {
                return employee.Gender == Gender.F;
            });
```
If you hover over employee in visual studio, you would see the compiler has rightly interpreted its type
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lixnapcszeock3v564c7.jpg)

Another cool feature of lambda expressions is if we have a single parameter we don't need to enclose it in brackets, we can get rid of those
```cs
 var femaleEmployees = employees.Where( employee=>
            {
                return employee.Gender == Gender.F;
            });
```
More to compact coding !!

If we are having just a single statement and returning a single value we can well get rid of the curlys and the return statement too !
 `var femaleEmployees = employees.Where( employee=> employee.Gender == Gender.F);`
And since we are inclined to have as much less written code as possible, a convention followed while writing lambda expressions is to name the parameters with single letters further reducing our code to
`var femaleEmployees = employees.Where( e=> e.Gender == Gender.F);`

And that's it ! That's how we reach the where of "Where" came from ! If you understand the Func delegate and the lambdas ,it is going to be easy to decipher and use those LINQ extension methods. You could evaluate even more complex conditions through the *Where* method.

A similar understanding can be extended to write the following extension methods as well 

*Any*
`public static bool Any<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,bool> predicate);`

*FirstOrDefault*
`public static TSource FirstOrDefault<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,bool> predicate);`

*SingleOrDefault*
`public static TSource SingleOrDefault<TSource> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,bool> predicate);`

I would have loved to discuss about *Join* and the *GroupBy* but I will save it to a later post.