Showing posts with label LINQ. Show all posts
Showing posts with label LINQ. Show all posts

Saturday, March 17, 2012

LINQ Lambda and Extension methods

This post is a gentle ramble through the application of Extensions and delegates and Funcs that go to make LINQ. I found it quite a lot to get my head around at first and I hope this explains it well. Because if it is explained well it is interesting. If I fail, then I would recommend you do some google/Bing searching. There must be stuff out there.

I have a post that describes Extension methods. It might be worth reading that first.

Example 1 - Creating a rather pointless Extension method to IEnumerable.
This example gives a method to the IEnumerable interface that will search for the first letter of a string and return the list. If you do not know what an extension method is, do read the other post. Unfortunately this post assumes knowledge of that.
Note the use of the Yield keyword. I have a post on that if you need it.

using System;
using System.Collections.Generic;
using MyExtensions;

namespace MyProgram
{
class Program
{
public static void Main (string[] args)
{
IEnumerable<string> names = new[] {"Will", "Bill", "Jill", "Bob" };
IEnumerable<string> nameThatStartwithB = names.NameBeginsWithLetter("B");
foreach (var name in nameThatStartwithB)
{
Console.WriteLine(name);
}
}
}
}

namespace MyExtensions
{
public static class NameFilterExtensions
{
//This is an Extension method for IEnumerable of string - note the "this"
// in front ot the IEnumerable.
public static IEnumerable<string> NameBeginsWithLetter(this IEnumerable<string> names, 
                                                  string startChar)
{
foreach(var s in names)
{
if (s.StartsWith(startChar))
{
yield return s;
}
}
}                                     
}
}


  • Note that the NameBeginsWithLetter(..) method is a static method and has the "this" keyword. This is an Extension method for the IEnumerable interface. Exactly in the same way that LINQ operators are built. In the same why that our extension method is in a namespace, the LINQ extension methods are defined in System.Linq
  • Note in the Main() function, how our method is a "member" of the names object - and IEnumerable object.
  • Also note that the namespace MyExtensions, which contains my extension method, is included in the Usings.

This example is a bit rubbish. It works but it's not very generic. The next example is more generic as we work towards a nice and elegant solution.

Making the Method Generic with Lambdas
The generic methods used by LINQ, the Select, Orderby etc. are inside the System.Linq namespace. There is an Enumerable class. In the following screen shot I have used dotPeek to decomplile the System.Core dll and in the System.Linq namespace we can get an idea of what is coming. Notice on the highlighted portion there is a bunch of generic looking <T>'s and the Func keyword. That's where we're heading though I didn't realise it till I just saw it!



If we decomplie the Where function we can see what Microsoft have done, and it's very close to our previous example. We can see the main parts that go to making this an extension method.



public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
      if (source == null)
        throw Error.ArgumentNull("source");
      if (predicate == null)
        throw Error.ArgumentNull("predicate");
      if (source is Enumerable.Iterator<TSource>)
        return ((Enumerable.Iterator<TSource>) source).Where(predicate);
      if (source is TSource[])
        return (IEnumerable<TSource>) new Enumerable.WhereArrayIterator<TSource>((TSource[]) source, predicate);
      if (source is List<TSource>)
        return (IEnumerable<TSource>) new Enumerable.WhereListIterator<TSource>((List<TSource>) source, predicate);
      else
        return (IEnumerable<TSource>) new Enumerable.WhereEnumerableIterator<TSource>(source, predicate);
    }


Example 2 - Using a Delegate
In this example I have created a delegate that is passed into the Extension method. As I see it, this is an improvement in two ways. (1), if we want to filter in a different way, we can write a new delegate method  and pass it in, rather than write a new Extension method on the IEnumerable object. (2), this separates the WHAT from the HOW. I mean that the Extension method says it is going to filter, but it doesn't know How it is going to filter. That, is defined by the delegate function.

namespace MyProgram
{
class Program
{
public static void Main (string[] args)
{
IEnumerable<string> names = new[] {"Will", "Bill", "Jill", "Bob" };
//IEnumerable<string> nameThatStartwithB = names.NameBeginsWithLetter("B");
IEnumerable<string> nameThatStartwithB = names.Filter(NameBeginsWithLetterB);
foreach (var name in nameThatStartwithB)
{
Console.WriteLine(name);
}
}
// This can be passed to the extension method. It is a bit more flexible 
// because we can write another method like this rather than anther 
// extension method.
static bool NameBeginsWithLetterB(string name)
{
return name.StartsWith("B");
}
}
}

namespace MyExtensions
{
public static class NameFilterExtensions
{
  // Notice this delegate function                                  
public delegate bool MyFilterDelegate<T> (T item);

  // Notice that the delegate is passed into the extension method
public static IEnumerable<T> Filter<T>(this IEnumerable<T> src, MyFilterDelegate<T> predicate)
{
foreach(var i in src)
{
if (predicate(i))  yield return i;
}
}  
}
}



Example 3 - Anonymous Delegates
I think that Anonymous functions, or anonymous delegates are so called because they do not appear in the call stack. They are "in-line" a-la functional programming. In this example we can use the in-line Delegate. This is now looking more like the LINQ syntax.

namespace MyProgram
{
class Program
{
public static void Main (string[] args)
{
IEnumerable<string> names = new[] {"Will", "Bill", "Jill", "Bob" };
//IEnumerable<string> nameThatStartwithB = names.NameBeginsWithLetter("B");
//IEnumerable<string> nameThatStartwithB = names.Filter(NameBeginsWithLetterB);
IEnumerable<string> nameThatStartwithB = names.Filter(delegate (string name)
                                                    {
return name.StartsWith("B");
                                        });
foreach (var name in nameThatStartwithB)
{
Console.WriteLine(name);
}
}
}
}


Example 4 - Remove the Delegate and use Lambdas
The designers of the language/complier decided that they could simplify the syntax for the above code and they decided that they could:
  • Remove the delegate keyword because the compiler knows the user will be passing in a delegate.
  • Remove the type of the parameter because we know that we are dealing with an IEnumerable of strings.
  • Remove the Return keyword.
  • Remove the  "{ }" around the return statement.
  • Add the "Goes to" operator, =>
  • Remove a superflous semi colon (you'll spot that one when you write this example)

And we end up with:


IEnumerable<string> nameThatStartwithB = names.Filter( (name) => name.StartsWith("B"));

This is the lambda expression and is so much easier to type, and read.


The class in full is as follows:

namespace MyProgram
{
class Program
{
public static void Main (string[] args)
{
IEnumerable<string> names = new[] {"Will", "Bill", "Jill", "Bob" };
IEnumerable<string> nameThatStartwithB = names.Filter( (name) => name.StartsWith("B"));
foreach (var name in nameThatStartwithB)
{
Console.WriteLine(name);
}
}
}
}



Example 5 - Using Func 
I have a post on Func. (Basically, Func is a type that encapsulates callable code)

We can use the Func type to simplify out Extension method. We do this by using Func to remove the delegate declaration.


Before:
namespace MyExtensions
{
public static class NameFilterExtensions
{                                  
public delegate bool MyFilterDelegate<T> (T item);
public static IEnumerable<T> Filter<T>(this IEnumerable<T> src, MyFilterDelegate<T> predicate)
{
foreach(var i in src)
{
if (predicate(i))  yield return i;
}
}  
}
}


After:
namespace MyExtensions
{
public static class NameFilterExtensions
{                                  
public static IEnumerable<T> Filter<T>(this IEnumerable<T> src, Func<T, bool> predicate)
{
foreach(var i in src)
{
if (predicate(i))  yield return i;
}
}  
}
}


And that is about it.

Friday, March 16, 2012

Extension methods in C#

I think these are clever. A neat compiler trick but where the idea came from I don't know.
What they provide.
They allow us to add methods to an object without changing the code for that object. Their main use is in LINQ.  How is it that LINQ can have a method that works on so many types. How did they do that? Well the solution was really quite clever - and simple.

At the bottom of LINQ is the IEnumerable interface and that is very basic and simple. It is something like this:

using System.Collections;

namespace System.Collections.Generic
{
public interface IEnumerable<out T> : IEnumerable
{
new IEnumerator<T> GetEnumerator();
}
}

GetEnumerator lets us enumerate, or loop through collections:

IEnumerable<string> names = new IEnumerable<string>[] {"Bill", "Will", "Jill" };
foreach (var name in names)
{
Console.WriteLine(name);
}

Really handy and used all the time.

As I said, IEnumerable is at the bottom of LINQ and Microsoft didn't want to change this every time a whizzo idea arrived so they created the Extension method. Using these, it appears as if IEnumerator has more and more methods, but actually it doesn't. It's smoke and mirrors. We can add methods to it, but not change it. What fun.

Using DateTime as an example
In C#, DateTime is a struct, and is sealed, so we can not inherit from it. If say, you wanted to add fancy functions to DateTime we would have a couple of options. We can write a utility class that you pass a DateTime object into and the date maths, the workings, can be hidden in there. We would therefore call this Utility class method throughout our code, passing the date object into it. We could, if we wanted to, make the class static with a static method. That's not really news.

In the example below there are two methods that show how we can implement a method on a DateTime. The first, GetPreviousYear(DateTime date) is the usual way to do this.
The second, GetPreviousYearExtensionVersion(this DateTime date), is the extension method way of doing things.
There are three important aspects to note about the extension menthol version:
  1. The class is static,
  2. The method is static,
  3. The parameter type declaration has "this" prefixing it.
namespace Stuff
{
class MyProg
{
public void DoMoreStuff()
{
DateTime date = new DateTime(2012, 3, 15);
int previousYear = MyDateHelper.GetPreviousYear(date);
DateTime date2 = new DateTime(2012, 3, 15);
int previousYear2 = date2.GetPreviousYearExtensionVersion();
}
}
public static class MyDateHelper
{
public static int GetPreviousYear(DateTime date)
{
return date.Year -1;
}
}
public static class MyDateHelperExtension
{
public static int GetPreviousYearExtensionVersion(this DateTime date)
{
return date.Year -1;
}
}
}

You can see that the first method is called using MyDateHelper.GetPreviousYear(date); 
That is ok, it seems reasonable because that's how we've done it for years. But the syntax of the extension method is much easier to understand I think. The previous call is, in this example, date.GetPreviousYearExtensionVersion(). That is a silly name and example. It would become, date.GetPreviousYear();
  • MyDateHelper.GetPreviousYear(date);
  • date.GetPreviousYear();
Now that is good.