Why the Linq expression IL results in omission of the Select projection whereas the corresponding method expression keeps the Select projection ?
I suppose these two pieces of code does the same.
var a = from c in companies
where c.Length >10
select c;
//
var b = companies.Where(c => c.Length > 10).Select(c => c);
//IL - LINQ
IEnumerable<string> a = this.companies.
Where<string>(CS$<>9__CachedAnonymousMethodDelegate1);
//IL
IEnumerable<string> b = this.companies.Where<string>
(CS$<>9__CachedAnonymousMethodDelegate4).Select<string, string>
(CS$<>9__CachedAnonymousMethodDelegate5);
Then why the difference in IL?
EDITED :
then why
var a = from c in companies
select c;
result in SELECT projection even inside IL. it can also be omitted right ?
The C# compiler is clever and remove useless statement from Linq. Select c is useless so the compiler remove it. When you write Select(c=>c) the compiler can't say that's the instruction is useless because it' a function call and so it doesn't remove it.
If you remove it yourself IL become the same.
EDIT :
Linq is a "descriptive" language : you say what you want and the compiler transforms it well. You don't have any control on that transformation. The compiler try to optimize function call and don't use Select because you don't do projection so it's useless.
When you write Select(c => c) you call a function explicitely so the compiler won't remove it.
var a = from c in companies select c;
var a = c.Select(elt=>elt);
Select is usefull in this example. If you remove it a has the type of c; otherwise a is an IEnumerable
#mexianto is of course correct that this is a compiler optimization.
Note that this is explicitly called out in the language specification under "Degenerate Query expressions." Also note that the compiler is smart enough to not perform the optimization when doing so would return the original source object (the user might want to use a degenerate query to make it difficult for the client to mutate the source object, assuming that it is mutable).
7.16.2.3 Degenerate query expressions
A query expression of the form
from x in e select x
is translated into
( e ) . Select ( x => x )
[...] 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.
In your second example, the call to Select is not redundant. If you would omit the Select call, the query would just return the original collection, whereas Select returns an IEnumerable.
In your first example, Where already returns an IEnumerable and the select clause doesn't do any work, so it is omitted.
Because in the query version there is no actual select projecting 'c' into something else, it is just passing on 'c' as-is. Which results in only a call to 'Where'.
In the second variation, you explicitly call 'Select' and thus do a projection. Yes, you are only returning the same objects, but the compiler will not see this.
Related
I have an Expression that converts one type of object to another type. The expression is as follows:
public Expression<Func<SQLRepository.ActionType, Model.ActionType>> DBActionTypeToActionType =
(SQLRepository.ActionType at) => new Model.ActionType()
{
ID = at.OID,
DisplayName = at.DisplayName
};
I can use the Expression like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select at).Select(DBActionTypeToActionType);
But I'd like to use it like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select DBActionTypeToActionType.Compile().Invoke(at));
I've been looking for a couple days now and I can only find references to doing this in the Where clause. It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
The reason it is important to do use the query syntax is that some of the objects that are being selected are composed of many sub-objects and trying to chain them all of the conversions together with the function notation will be much harder to write and maintain.
It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
That's not true. Query notation always goes via a lambda expression. For example
from x in y select z
ends up as
y.Select(x => z)
That means if you've already got an expression tree that you want to pass directly as the argument to Select, you can't use query expressions because there's this extra level of indirection.
Now the options available depend on where you need to apply the predefined expression. You can always use it in the source, and then continue with the query:
var query = from foo in dc.ActionTypes.Select(DBActionTypeToActionType)
where foo.Stuff
select foo.Other;
Or using it at the end is easy:
var query = (from bar in dc.ActionTypes
where bar.Stuff
select bar).Select(DBActionTypeToActionType);
Does that help at all?
I have the following query:
var vendors = (from pp in this.ProductPricings
join pic in this.ProductItemCompanies
on pp.CompanyId equals pic.CompanyId into left
from pic in left.DefaultIfEmpty()
orderby pp.EffectiveDate descending
group pp by new { pp.Company, SortOrder = (pic != null) ? pic.SortOrder : short.MinValue } into v
select v).OrderBy(z => z.Key.SortOrder);
Does anyone know how the last OrderBy() is applied? Does that become part of the SQL query, or are all the results loaded in to memory and then passed to OrderBy()?
And if it's the second case, is there any way to make it all one query? I only need the first item and it would be very inefficent to return all the results.
Well it will try to apply the OrderBy to the original query since you are still using an IQueryable - meaning it hasn't been converted to an IEnumerable or hydrated to a collection using ToList or an equivalent.
Whether it can or not depends on the complexity of the resulting query. You'd have to try it to find out. My guess is it will turn the main query into a subquery and layer on a "SELECT * FROM (...) ORDER BY SortOrder" outer query.
Given your specific example the order by in this situation most, likely be appliead as part of the expression tree when it getting build, there for it will be applied to sql generated by the LINQ query, if you would convert it to Enumarable like ToList as mentioned in another answer then Order by would be applied as an extension to Enumerable.
Might use readable code, because as you write it is not understandable.
You will have a problem in the future with the linq statement. The problem is that if your statement does not return any value the value will be null and whenever you make cause a exception.
You must be careful.
I recommend you to do everything separately to understand the code friend.
I don't know whether the term of above title is appropriate.
Just like a and b:
var list = Enumerable.Range(0, 100);
var a = from l in list
where l % 2 == 0
select l;
var b = list.Where(l => l % 2 == 0);
When should I use each of them? And any difference?
None, Query expression compiles into Method expression.
Query Syntax and Method Syntax in LINQ (C#)
Because queries return an IEnumerable, you compose them in method
syntax by chaining the method calls together. This is what the
compiler does behind the scenes when you write queries by using query syntax
Also see: LINQ Query Expressions (C# Programming Guide)
At compile time, query expressions are converted to Standard Query Operator method calls according to the rules set forth in the C#
specification. Any query that can be expressed by using query syntax
can also be expressed by using method syntax. However, in most cases
query syntax is more readable and concise. For more information, see
C# Language Specification and Standard Query Operators Overview.
Apart from that one place where I have found something that can't be done in Query expression is to get the index along with the item. For example you can do following in method syntax:
var result = list.Select((r,i) => new { value = r, index = i});
In query expression an external variable has to be defined to achieve this purpose. Here is a similar discussion with answer from Jon Skeet
No
There is no difference between them.
From Query Syntax and Method Syntax in LINQ
Because queries return an IEnumerable, you compose them in method
syntax by chaining the method calls together. This is what the
compiler does behind the scenes when you write queries by using query
syntax. And because a query variable does not store the results of the
query, you can modify it or use it as the basis for a new query at any
time, even after it has been executed.
Also from LINQ Query Expressions
At compile time, query expressions are converted to Standard Query
Operator method calls.
Query expression is transformed into standard method calls by compiler.
var a = from l in list
where l % 2 == 0
select l;
var b = list.Where(l => l % 2 == 0);
These two are exactly the same in compiled code.
However, not all methods have a keyword associated in query expression syntax.
There's no difference, it's a matter of personal preference. You can even mix the two styles if you want to.
The Linq keywords are translated into the method call syntax by the C# compiler.
The difference, in fact, is no.
In fact, it is one and the same thing, except that the expression for the $a$ the compiler converts to an expression equivalent to expression for $b$.
I have an Expression that converts one type of object to another type. The expression is as follows:
public Expression<Func<SQLRepository.ActionType, Model.ActionType>> DBActionTypeToActionType =
(SQLRepository.ActionType at) => new Model.ActionType()
{
ID = at.OID,
DisplayName = at.DisplayName
};
I can use the Expression like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select at).Select(DBActionTypeToActionType);
But I'd like to use it like this:
var linq = (from at in dc.SQLRepositoryDC.ActionTypes select DBActionTypeToActionType.Compile().Invoke(at));
I've been looking for a couple days now and I can only find references to doing this in the Where clause. It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
The reason it is important to do use the query syntax is that some of the objects that are being selected are composed of many sub-objects and trying to chain them all of the conversions together with the function notation will be much harder to write and maintain.
It seems that if I'm able to use the function calls to do this, it should be possible using the query syntax.
That's not true. Query notation always goes via a lambda expression. For example
from x in y select z
ends up as
y.Select(x => z)
That means if you've already got an expression tree that you want to pass directly as the argument to Select, you can't use query expressions because there's this extra level of indirection.
Now the options available depend on where you need to apply the predefined expression. You can always use it in the source, and then continue with the query:
var query = from foo in dc.ActionTypes.Select(DBActionTypeToActionType)
where foo.Stuff
select foo.Other;
Or using it at the end is easy:
var query = (from bar in dc.ActionTypes
where bar.Stuff
select bar).Select(DBActionTypeToActionType);
Does that help at all?
I was playing around with expression trees and various Linq syntax. I wrote the following:
using (NorthwindDataContext DB = new NorthwindDataContext())
{
DataLoadOptions dlo = new DataLoadOptions();
// Version 1
dlo.AssociateWith<Customer>(c => c.Orders.Where(o => o.OrderID < 10700).Select(o => o));
// Version 2
dlo.AssociateWith<Customer>(c => from o in c.Orders
where o.OrderID < 10700
select o);
}
The Version 1 method returns an error saying "The operator 'Select' is not supported in Subquery."
While Version 2 runs just fine. From what I understand I am writing the exact same thing, but one is with the "dot" notation syntax and the other is query expression syntax.
Am I missing something here? Why the error on one but not the other "if" they are in fact the same query?
To expand on Daniel's answer, the select o is known as a degenerate query expression - and it's removed by the C# compiler. So your query is translated to:
c.Orders.Where(o => o.OrderID < 10700)
Note that without the where clause, however, the compiler would still include the Select call, so:
from o in c.Orders
select o
is translated to
c.Orders.Select(o => o)
From section 7.15.2.3 of the language spec:
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.
You don't need the .Select(o => o) in your query.