I have moved!

I've moved my blog
CLICK HERE

Thursday 6 November 2008

The Weirdness of Linq Query Expressions

What does this bit of code do?

var result = from n in 5 where (n == 5) select (n + 1);

It looks completely hopeless. How can you loop through the contents of the number 5? The C# language reference says of the from clause:

The data source referenced in the from clause must have a type of IEnumerable, IEnumerable<T>, or a derived type such as IQueryable<T>.

But that is a lie!

The above code is translated into this:

var result = 5.Where(n => n == 5).Select(n => n + 1);

So in fact it is not necessary for the data source (the thing after the in keyword) to be enumerable at all. The only thing it must have is methods (or extension methods) called Where and Select. So let’s define them for all types:

public static class Crazy
{
    public static T Where<T>(this T source, Func<T, bool> pred)
    {
        if (pred(source))
            return source;

        return default(T);
    }

    public static T Select<T>(this T source, Func<T, T> select)
    {   
        return select(source);
    }   
}

So Where is a function that either returns the value passed into it, or the default value for the type, depending on the result of the predicate. This is sort-of analogous to what the Linq-to-objects version of Where does. And Select is completely trivial.

With these definitions, the original line of code produces an integer with the value 6.

Could this kind of abuse be turned into a valid use? Obviously it depends on whether you can think of useful definitions of Where and Select for types other than IEnumerable<T>. Bear in mind that all query expressions begin with fromin,  so it will look mighty confusing unless the data source is list-like.

No comments: