I want to enable LinQ query syntax over my classes. I think query syntax is translated to method syntax, for example:
var query = from p in new Class1
I'm pretty sure that the translation from query syntax to method syntax optimizes the call to Select
away if it states an identity projection.
Since p => p
would project everything to itself and the Where
clause already added an abstraction layer between the source sequence and the result, this call is no longer necessary.
So
var query = from p in new Class1<Product>()
where p.Id == "1000"
select p;
is only translated to
var query = new Class1<Product>().Where(p => p.Id == "1000");
But I admit that I only guess that and am still searching for the relevant specification part.
Update: Jon was faster
Your understanding is little incorrect, the following query :
var query = from p in new Class1<Product>()
where p.Id == "1000"
select p
will translate to :
var query = new Class1<Product>().Where(p => p.Id == "1000");
and when you are removing the where
part:
var query = from p in new Class1<Product>()
select p;
now it will be translated to something like:
var query = new Class1<Product>().Select(p=>p);
Someone knows why?
Yes, because that's what the language specification says to do. The query expression translation is all in section 7.16.2 of the C# 5 specification.
Section 7.16.2.5 explains why your initial example is incorrect - Select
won't be called:
A query expression of the form
from x in e select v
is translated into
( e ) . Select ( x => v )
except when v is the identifier
x
, the translation is simply( e )
For example
from c in customers.Where(c => c.City == “London”) select c
is simply translated into
customers.Where(c => c.City == “London”)
However, that isn't the case for degenerate query expressions which are covered in 7.16.2.3 - which explains what happens when you remove your where
clause:
A query expression of the form
from x in e select x
is translated into
( e ) . Select ( x => x )
The example
from c in customers select c
Is translated into
customers.Select(c => c)
A degenerate query expression is one that trivially selects the elements of the source. A later phase of the translation removes degenerate queries introduced by other translation steps by replacing them with their source. It is important however to ensure that the result of a query expression is never the source object itself, as that would reveal the type and identity of the source to the client of the query. Therefore this step protects degenerate queries written directly in source code by explicitly calling Select on the source. It is then up to the implementers of
Select
and other query operators to ensure that these methods never return the source object itself.