This is my personal blog. The views expressed on these pages are mine alone and not those of my employer.

Wednesday, 27 August 2014

Why LINQ requires you to Func?

When LINQ appeared on our screens it brought along a requirement under the guise of 'Func' whenever you wanted to do anything substantial, such as supply the contents of a where clause:

What exactly is Func? What are we actually being asked for here?  This is a journey that begins with delegates.

First let's consider how we create an object:

As you can see this takes three steps:

  • We define the a class (Car)
  • We create a variable of that type
  • Then we create an instance of the class and set the variable to a reference of it

A bit simple? Stick with me...

Now lets see how we do this with delegates.  I invite you to spot the difference:

In both instances Car acted as a pointer to some functionality, the first was a reference to an instance of a class whereas the second was reference to a method.  You've spotted the difference.

Class type = Reference to a object
Delegate type = Reference to a method

Directly from the C# Spec:
1.11 Delegates

A delegate type represents references to methods with a particular parameter list and return type. Delegates make it possible to treat methods as entities that can be assigned to variables and passed as parameters.

That last sentence is extremely important.  Delegates allow us to pass references to methods in the same way we can pass references to objects.

This is the purpose of Func.  Instead of being forced to define our own delegate (what we did in the second example, named Car) we're provided with a definition of a delegate of which we have to provide a suitable reference.

Let me hammer this home:
Usually we call methods which a reference (or value of) an object, instead the Where method is requesting a reference to a method which is the same type of Func.
Lets see a concrete example:

Scenario: Select all names beginning with M

To do this I need to create a method that tests a given item, and return true if it begins with M:

However because of these features introduced in (introduced in C# 2*):

- Removing the awkward delegate syntax
- Anonymous methods, allowing you to define a delegate instance's action in-line

we can supply it in a way I suspect you're familiar with:

* Surprising isn't it, this has been available since 2005!

Hopefully you can see that the only difference is that we've compressed the method definition, moving towards a more fluid, expressive form of programming.  Which, in conjunction with anonymous methods is the only purpose of Func.

There are 17 varieties of Func, each one specifying a different amount of parameters to enable you to pick the right one for your task.  There is also a sibling Action which has the same purpose expect for not returning a value.

So...why not have a glance over your codebase? How many times have you used Func without giving it a second thought?  Even better, how could you produce your own methods that accept functionality as a parameter in the form of Func?

No comments:

Post a Comment