Query expressions

DRAFT DRAFT DRAFT DRAFT

These are my raw notes on section 7.16 of the C# Language Specification. Section 7.16 falls within section 7 on expressions.

Heuristic Model

  1. Notes . Add notes for each section.
  2. Definitions . Add definitions for the chapter.
  3. Examples . After adding definitions, then add examples.
  4. Edit . After adding examples, then edit for readability etc.

My Personal Conventions

Intro

query expression syntax is similar to that of relational and hierarchical query languages

Ambiguities

The way to mixing contextual keywords into strings.

The above are keywords when they occur anywhere within a query expression.

To use these keywords within a query expression, prefix them with @

from @select
in (new string[] { "from", "select" })
select @select

Where a query expression is any expressions that

Translation

The steps for turning a query expression into fluent syntax.

Where
Select
SelectMany
Join
GroupJoin
OrderBy
OrderByDescending
ThenBy
ThenByDescending
GroupBy
Cast

1. Select and groupby clauses with continuations

Example

from c in customers group c by c.Country into g select new { Country = g.Key }

becomes

from g in ( from c in customers group c by c.Country ) select new { Country = g.Key }

then becomes

customers.GroupBy(c => c.Country) . Select ( g => new { Country = g.Key } )

2. Explicit range variable types

from

join

Example

from Customer c in customers where c.City == "London" select c

becomes

from c in customers.Cast<Customer>() where c.City == "London" select c

then becomes

customers.Cast<Customer>().Where(c => c.City == "London")

Note

The .Cast<T>() operates on each object in the collection (as opposed to casting the collection).

3. Degenerate query expressions

A degenerate query expression is one the trivially selects the elements from the source.

Example

from c in customers select c

becomes

customers.Select(c => c)

Notes

4. From , let , where , join , and orderby clauses

A query expression with a...

...second from clause followed by a...

... select clause

something other than a select clause

Recall that the * is the transparent identifier. It captures multiple range variables and later becomes an anonymous object or function. In the above case, it later becomes new { x1, x2 }

Note, in both the above examples, the range variables of both from clauses stay in scope; that is, both are available in subsequent clauses.

let clause

The variable defined within the let clause has access to the initial range variable and, along with it, is available through the rest of the query.

where clause
join clause without an into followed by a

select clause

something other than a select clause

In this case, the transparent identifier * holds the place of the anonymous new { x1, x2 }

join clause with an into followed by a

The into makes the join into a group join.

select clause

The output here is the initial range variable x1 and the group formed from the second range variable x2. In other words, x1 remains in scope but x2 doesn't because it's behind g.

something other than a select clause

orderby clause

followed by descending

5. Select clauses

The =&gt; is a projection from each value of x into v . If v is simply a repeat of x , then the translation is just ( e ) .

6. Group by clauses

The exception is when v is the identifier x , in which case the result is ( e ) . GroupBy ( x =&gt; k )

7. Transparent identifiers

Pattern

Terminology in Approximate Order of First Occurrence