Anders Miltner
Anders Miltner

Reputation: 263

How intelligent is Linq with IOrderedEnumerable and Where

so let's say I have an IEnumerable dates and I want to get the dates within a range.

Is Linq and IOrderedEnumerable intelligent enough to realize the ability to choose faster algorithms given that the dates are now ordered.

So consider this:

IOrderedEnumerable<ObjectWith2DateTimes> orderedDates = dates.OrderBy(x => new Tuple(x.datetime1,x.datetime2));

...
this is called a bunch
...
    DateTime afterDateTime = (some datetime)
    DateTime beforeDateTime = (other datetime)
    yield return orderedDates.Where(x => x.datetime1 >= afterDateTime && x.datetime2 <= beforeDateTime)

If isn't smart with this implementation, is there some other implementation that would make it smart?

Upvotes: 1

Views: 385

Answers (4)

Loki
Loki

Reputation: 421

LINQ-to-objects works with delegates and treats them as blackboxes. So it does not know that your where condition has any relation to the earlier ordering operation. So it does not perform this optimization.

It's even worse than that, the sorting will be done each time you evaluate the query, even if it's shared. You need to materialize it with ToArray or ToList. Then you can use the built-in binary search function to speed this up.

Upvotes: 0

Hans
Hans

Reputation: 2320

No it's not smart enough to do that. Enumerable.Where<TSource> takes a Func<TSource, bool>, not an Expression<Func<TSource, bool>> like Queryable.Where<TSource>. So you could do it with an IQueryable, but you'd need a query provider that can do that. It's probably not worth the trouble.

However, something like this should do:

orderedDates
    .SkipWhile(x => x.datetime1 < afterDateTime)
    .TakeWhile(x => x.datetime2 > beforeDateTime)

Upvotes: 5

MarcinJuraszek
MarcinJuraszek

Reputation: 125650

No. Where extension method does simple, linear search over all items in your collection and returns element if it follows your predicate. You can think of it as:

foreach(var item in source)
    if(predicate(item))
        yield return item;

Upvotes: 0

Mike Strobel
Mike Strobel

Reputation: 25623

No; the Where operator has no idea what your predicate does; it just knows to invoke a delegate that tells it whether to include an item in the result set. It would be possible for a query provider to do this with IOrderedQueryable, as the query provider would be able to analyze the expression tree. I do not know if any query providers actually do that kind of analysis.

Upvotes: 1

Related Questions