views:

41

answers:

1

I've started looking over the reactive framework. Very nice stuff. But while looking at code samples it got me confused. The linq syntax works with the IQueryable. I thought that linq only works with IEnumerable. On what does the C# compiler bases it's linq to extension methods conversions? Does it require a set of methods with a specific interface?

+4  A: 

Not quite. It's just a syntactic translation. For example, the compiler will translate this:

var query = from item in source
            select item.Property;

into

var query = source.Select(item => item.Property);

It does that without knowing anything about the Select method. It just does the translation, then tries to compile the translated code.

All the translations are carefully documented in section 7.16 of the C# 4 spec (and the equivalent for earlier editions, of course).

In the case of Rx, it calls the extensions on IObservable<T> and IQbservable<T>. In the case of Parallel Extensions, it calls the extension methods on ParallelQuery<T>.

You can do some mad stuff with it - I have a blog post which gives a few examples. Here's another odd one:

using System;
using System.Linq;

namespace CornerCases
{
    class WeirdQueryExpression
    {
        static WeirdQueryExpression Where(Func<int, int> projection)
        {
            return new WeirdQueryExpression { Select = ignored => "result!" };
        }

        Func<Func<string, bool>, string> Select { get; set; }

        static void Main()
        {
            string query = from x in WeirdQueryExpression
                           where x * 3
                           select x.Length > 10;

            Console.WriteLine(query);
        }
    }
}

The query translates to:

WeirdQueryExpression.Where(x => x * 3)
                    .Select(x => x.Length > 10);

... which is a call to a static method, which returns a WeirdQueryExpression, followed by accessing the Where property which returns a Func<Func<string, bool>, string>. We then call that delegate (passing in another delegate) and assign the result to query.

Funky, huh?

Jon Skeet
Just to add (in order to help the OP), LINQ finds the extension methods for IQueryable via the Queryable class:http://msdn.microsoft.com/en-us/library/system.linq.queryable.aspx
Reed Copsey