Thursday, 18 November 2010

AsEnumerable, IQueryable, IEnumerable

Some Basic stuff that I guess is only useful to me...
The other day while digging into some code I came across the AsEnumerable extension method. It's a pretty important one. Let's say we have an IQueryable and we're chaining queries on it (that is, the extension methods in System.Linq.Queryable). Everything works fine while those queries can be expressed as expressions (the methods in Queryable expect Expressions) and the IQueryProvider associated to our IQueryable object is is able to deal with them (transform them to Sql in the case of Linq To Sql).
If we have one query that can not be expressed as a Expression or that our associated IQueryProvider is not going know how to process, we'll need to resort to Linq to Collections (that is, the extension methods in System.Linq.Enumerable).
So, how do we force the compiler (extension methods are static, so no dynamic VTables polymorphic magic, just static binding) to invoke the right method?. We just convert it to IEnumerable using AsEnumerable, and then the compiler will bind to the Linq.Enumerable methods.

Everything fine so far, but what sounded a bit odd to me about all this is that given that IQueryable inherits from IEnumerable (IEnumerable -> IQueryable), and as aforementioned all this is static binding, isn't it enough with just upcasting from IQueryable to IEnumerable?
Of course it is (as confirmed by the answer by David B in this good entry in StackOverflow), so it seems it's just a matter of style, AsEnumerable fits better in all the method chaining.

Copy and paste from David B answer:


IEnumerable orderQuery = dataContext.Orders
.Where(o => o.Customer.Name == "Bob")
.AsEnumerable()
.Where(o => MyFancyFilterMethod(o, MyFancyObject));



IEnumerable orderQuery =
((IEnumerable)
(dataContext.Orders.Where(o => o.Customer.Name == "Bob")))
.Where(o => MyFancyFilterMethod(o, MyFancyObject));

No comments:

Post a Comment