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?
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?