Differences in LINQ vs Method Expression

Why does the Linq IL expression result in the lack of a Select projection, while the corresponding method expression supports Select Select?

I believe that these two pieces of code do 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 is the difference in IL?

EDITED : why

  var a = from c in companies select c; 

leads to SELECT output even inside IL. can it also be skipped correctly?

+6
source share
4 answers

In your second example, calling Select is not redundant. If you omit the Select call, the query will simply return the original collection, while Select will return IEnumerable.

In the first example, where IEnumerable is already returned, and the select clause does not do any work, it is therefore omitted.

+3
source

The C # compiler is smart and removes useless instructions from Linq. Choosing c is useless, so the compiler removes it. When you write Select (c => c), the compiler cannot say that the instruction is useless because it is a function call, and therefore it does not delete it. If you delete it yourself, IL will become the same.

EDIT: Linq is a β€œdescriptive” language: you say what you want, and the compiler will convert it well. You have no control over this conversion. The compiler will try to optimize the function call and not use Select because you are not projecting, so this is useless. When you write Select (c => c), you call the function explicitly, so the compiler does not delete it.

 var a = from c in companies select c; var a = c.Select(elt=>elt); 

The selection is useful in this example. If you delete it, it will have type c; otherwise a is IEnumerable

+5
source

@mexianto is, of course, correct that this is compiler optimization.

Note that this is explicitly called in the language specification in the section "Degeneration of expression expressions". Also note that the compiler is smart enough not to perform optimizations when it will return the original source object (the user may want to use a degenerate request to make it difficult for the client to modify the original object, assuming that it is modified).

7.16.2.3 Degenerate query expressions

Form Request Expression

 from x in e select x 

translates to

 ( e ) . Select ( x => x ) 

[...] A degenerate query expression is an expression that trivially selects source elements. The later translation phase removes the degenerate queries introduced by the other translation steps, replacing them with its source. It is important, however, to ensure that the result of the query expression is never the source of the object itself, as this would reveal the type and source for the client of the request. Therefore, this step protects degenerate queries written directly in the source code explicitly by calling Select Source. It is then that the executors of the Select and other query operators to ensure that these methods will never return the original object.

+5
source

Because the request version does not have the actual choice of projecting 'c' into something else, it just passes 'c' as-is. This only results in a Where call.

In the second option, you explicitly call Select and, therefore, perform the projection. Yes, you return only the same objects, but the compiler will not see this.

+1
source

Source: https://habr.com/ru/post/898257/


All Articles