Req27: Allow query syntax in For Each

[This post is part of a series, "wish-list for future versions of VB"]

 

IDEA: Allow "For Each x In collection Where x>10", and other query expressions. We should allow this kind of code:

For Each x In collection Where x > 5

Currently we're forced to use awkward workarounds:

For Each x In From x_ In collection Where x_ > 5

For Each x In collection.Where(Function(x_ As Integer) x_ > 5)

For Each changedEntity In entityIndex.AllEntities.Where(
Function(x) x.ChangeTracker.State = ObjectState.Deleted)

 

IDEA 1: Allow only "Where" in For Each statements

IDEA 2: Allow arbitrary LINQ queries in For Each statements

 

This looks like a simple enough request, but it's not... The issue is that For Each uses the Collection Pattern: it looks for an accessible method or extension method named GetEnumerator, and on that it looks for MoveNext/Current; or failing that it looks for IEnumerable(Of T); or failing that it looks for IEnumerable. Meanwhile, a LINQ query use the Query Pattern : it looks for a conforming Select method, or failing that AsEnumerable/AsQueryable, or failing that Cast.

How to deal with this "impedance mismatch"? One solution is to go for IDEA 1, i.e. we figure out up-front which limited set of LINQ-like operators we want to allow. The problem with this is that it's so limiting, and we might get the set of operators wrong, and they wouldn't quite behave like thier LINQ counterparts.

Another solution is to go for IDEA 2, but say that every "querying For Each" statement is merely syntactic sugar for some LINQ query, e.g. "For Each x in coll where x>5" is merely syntactic sugar for "For Each x in (From x_ in coll where x_ > 5)".

Then we worry about performance. The compiler generates faster code when you "For Each" over an array than when you For Each over a collection. We would want "For Each x in coll Where x<5" to be exactly as performant as "For Each x in coll : If Not x<5 Then Continue".

 

Provisional evaluation from VB team: We're torn. It's a nice feature. But performance concerns push us to IDEA 1 with its problems, while generality/usability concerns push us to IDEA 2 with its problems.

What do you think? Would you like to see the more limited IDEA 1? With which LINQ-like query operators? Or would you prefer to see the more general IDEA 2?