In the previous article of the LINQ series, we about Aggregate functions.
The Restriction operator, as the name suggests, restricts the flow of data based on some condition.
The WHERE standard query operator belongs to this category.
Just like in SQL, the WHERE operator in LINQ is used to filter the records. The filter expression in LINQ is specified using a predicate and this predicate is a function used to test each element based on a condition.
Let's see an example.
Example 1
For this example, I have a List<int> of Digits in my console application.
Now let's say we want to retrieve and display only the odd numbers from this list collection and for that we can use a WHERE function.
- IEnumerable<int> OddNumber = Digits.Where(x => x % 2 != 0);
x is a parameter of type int and => x % 2 != 0 is a Boolean expression.
The next step is to loop through each item present in OddNumber.
- foreach(int i in OddNumber) {
- Console.WriteLine(i);
- }
Run the application.
Now, look at the type this predicate expects, When I say Digits.Where(
It expects a parameter of type Func<int,bool>.
So, what is this Func? To find that right-click on the Where function and select Go To Definition.
The first thing you will see in the preceding image is that there are two methods with the same name but with different overloaded parameters.
The next thing you will notice is that here in the Where() function, it has two parameters to pass in but when we were passing the predicate in our main project it shows only one parameter value must be passed.
The reason is, this Where() function is implemented as an extension method. To understand the rules of extension methods, click here.
Now, select Func<TSource,bool> and press F12 to go to the definition.
You will notice that this Func is actually a delegate. So what is a delegate?
A delegate is nothing but a type-safe function pointer.
If you go back and look at the intellisense we get for the parameter in the Where() function, Func<int,bool> and in the preceding delegate it states Func<in T, out TResult>. That means the first parameter is the input parameter and the second parameter is an output parameter.
Digits.Where (x- this x is an input parameter of type int.
=> x % 2 != 0 – this expression will give us true or a false.)
So, what will happen if I change the expression x % 2 != 0 to x + 2?
We will get a compile time error because this expression will give us an integer back and if you hover the mouse over this expression as in the following:
It states ”cannot implicitly convert type int to bool” and this makes sense, because a delegate is a type safe function pointer meaning the type of the delegate and the method it is pointing to must be the same and in the Where function, Func delegate expects a parameter of type bool.
But we are passing the value of type int and that's the reason we got the error.
Example 2
In this example we will see how to do the same thing by writing T-SQL like queries.
In SQL Server, we start from a SELECT clause but in LINQ we start from the FROM clause.
- From any_meaningful_name in source
- where condition
- select name_specifed_in_the_from_clause;
Run the application.
Example 3
There is another overloaded version of the Where() function that expects two input parameter and an output parameter. The first parameter is the sequence of values that will be filtered, the second parameter holds the Index of the sequence values and the third parameter is the boolean output parameter.
Let's say we want to retrieve all the odd numbers but we want only those odd numbers whose index value is even.
(value, index) is the input parameter of type integer.
Value % 2 != 0 is the first expression && value % 2 == 0 is the second expression, when both of the conditions are true, we will get the numbers.
Run the application.
When we used the first overloaded version, we got the following odd number output.
I hope you like it.
Thank you.