Tuesday, March 19, 2024 09:12

Table of contents >> LINQ > Writing custom LINQ extension methods

Writing custom LINQ extension methods

In the previous lesson, when I introduced you to a preview of what LINQ looks like, I ended up with this code:


And we learned that the free form syntax of LINQ is the same thing as the declarative syntax of LINQ, which is also the same with some bunch of extension methods for the IEnumerable interface, declared inside a class called Enumerable.

If you remember the lesson about extension methods, I was saying there that the compiler is first looking to the closest scope for methods name, and moves outwards. So, the closest scope for the Where() function call in the above code is the Program class. If it finds a function called Where() inside of it that has the required signature, it uses it; if it doesn’t find it, it will start looking in the codes of all the imported libraries within the using directives at the top of the file, where it looks inside the using System.Linq; code and finds the Where() function inside the Enumerable static class.

To prove this, and to also dispel the “magic” involved in LINQ extension methods, I am going to write my own version of a Where() function.

Since the Where() function is just an extension method for the IEnumerable interface, and since extension methods are declared only inside static classes, first thing I need to do is to make my Program class static as well. Afterwards, I could just copy the signature of the Where() function from the Enumerable class and make mine generic as well, but since my numbers variable is just an int array, I will make only an extension method for the int array too, for simplicity. Remember, an array also implements IEnumerable, that is why I am able to use my extension method for the LINQ queries:

See code changes


Legend:

  • green lines with a plus near the line numbers are newly added lines
  • red lines with a minus near the line numbers are removed lines



And now, the explanation: the first parameter, this int[] numbers, just indicates that we are creating an extension method for an int array (I explained the meaning of this in a previous lesson), while the second is just a delegate of type Func that takes an int as parameter and returns a bool. The rest is easy: I iterate over all the numbers in the numbers array, and for each of them, I pass them through the Func delegate. All of them which pass through, are yielded back.

Now, since I have three ways of doing the same LINQ stuff (the free form syntax, the declarative syntax and the static methods call), only the first two of them will actually call my version of Where(), because in the third one I explicitly call the Where() function inside the Enumerable class. We can set a breakpoint inside my custom Where() function and check if the execution reaches it:

and we can see that it does. And the result looks the same as in the case of the “real” Where() function:

Tags: , , ,

Leave a Reply



Follow the white rabbit