C # Review notes (4)--c#3: Innovative Ways to write code (query expressions and LINQ to Object (bottom))

Source: Internet
Author: User

query expressions and LINQ to Object (bottom)

Most of what we're going to look at next will involve transparent identifiers .

Let clauses and transparent identifiers

The LET clause simply introduces a new scope variable. His value is based on the other range variables. let identifier = expression;

First, we'll show you the sort by user name length that doesn't apply to let operators:

var  from inch sampledata.allusers                                    by user. Name.length                                  select  user;             foreach inch Querywithoutlet)            {                Console.WriteLine ($"{user. Name} ' s length is {user. Name.length}");            } ...

It can be seen that in order to sort by name forced to use two times name.lengthl to query. This is quite a performance-intensive. So, there needs to be a way to avoid this kind of redundancy calculation, which leads to the let operation: it evaluates an expression and introduces a new range variable.

...  varquery = fromUserinchsampledata.allusers Let length=user. Name.length bylengthSelect New{length = length, Name =user.            Name}; foreach(varIteminchquery) {Console.WriteLine ($"{item. Name} ' s length is {item.length}"); }...

The code above produces the same results, except that only one length operation is computed. The code listing introduces a new scope variable: length, which contains the lengths of the user names (for the current user in the original sequence). We then use the new range variable for sorting and the final projection. Did you find the problem? We need to use two range variables, but the lambda expression will only pass a parameter to select (for the reason behind it)! This is where the transparent identifier comes in.

We used two range variables in the final projection, but the Select method only works on a single sequence. How do you merge range variables together? The answer is to create an anonymous type to contain two variables, but you need to make a clever conversion so that it looks like you actually applied two parameters in the SELECT and order clauses.

Demonstrates this process:

The execution of the preceding code listing, where the LET clause introduces the length range variable.

The following is the translated code:

... var translatedquery = sampledata.users                new {user, length = user. Name.length})                = z.length)                new {Name = z.user.name, Length = z.length});.. 

Each part of the query is appropriately adjusted: for the original query expression, referring directly to user or length, if the reference occurs after the LET clause, use Z.user or z.length instead. Here the name Z is chosen randomly-everything is hidden by the compiler.

It is necessary to note that an anonymous type is only an implementation, because the C # specification does not strictly stipulate the transfer process of transparent identifiers, but the C # specification simply describes how the transparent identifiers should behave. The existing compilers of C # are implemented by anonymous types and do not know what will happen later.

Join

A junction in LINQ is similar to the concept of a junction above SQL, except for the sequence of join operations above LINQ. LINQ has three different types of joins, but not all with the Join keyword, first of all to look at join joins that are similar to inner joins in SQL.

On the junction, I'm going to say one of the most important conclusions: the left side of the junction is streamed, and the right side is buffered, so the smaller sequence should be placed to the right of the junction as much as possible when connecting two sequences. This conclusion is important, so I'm going to mention it several times in the chapter.

The MSDN documentation describes the related sequences as inner and outer (you can view the Ienumerable<t> when describing the Jon method for the in-compute junction). Join () method. )。 This is only used to distinguish between two sequences of names, not really within the meaning of the junction and Outer Junction. for Ienumerable<t>. For join (), outer refers to the left side of the join, and inner refers to the right side of the join.

First look at the syntax of join:

The type of left-key-selector must match the type of the Right-key-selector (which is also valid for a reasonable conversion), and the meaning is equal, and we can't do it. A person's date of birth is associated with the population of a city.

The sign of the junction is "equals" instead of "=" or "= =".

It is also entirely possible for us to use anonymous types as keys, because anonymous types implement appropriate equality and hashing. If you want to create a multi-column key, you can use anonymous types.

Instance:

Static voidMain (string[] args) {            varquery = fromDefectinchsampledata.alldefects Join Subscriptioninchsampledata.allsubscriptions on defect. Project equals subscription. ProjectSelect New{defect. Summary, subscription.            EmailAddress}; foreach(varIteminchquery) {Console.WriteLine ($"{item. Emailaddress}-{item. Summary}");        } console.readkey (); }

We can invert the sequence on both sides of the join, and the result returns the same content, except in order, in the LINQ to object implementation, the order in which the entries are returned is: First, all the paired data of the 1th element in the left sequence can be returned (in the order of the right sequence). It then returns all paired data using the 2nd element in the left sequence, and so on. The right-hand sequence is buffered, but the left sequence is still streamed-so if you're going to join a huge sequence to a very small sequence, you should use the small sequence as the right sequence if possible. This operation is still deferred: when the 1th pair of data is accessed, it begins execution and then reads the data from a sequence. At this point, it reads the entire right-hand sequence to create a mapping from the key to the values that generate the keys. After that, it doesn't need to read the right sequence again, so you can iterate over the left sequence to generate the appropriate data pair.

Shows the two different sequences used as data sources in the preceding code. (Sampledata.alldefects, defects and sampledata.allsubscrption, subscription)

We usually need to filter the sequence, and filtering before the join is much more efficient than after the join.

Static voidMain (string[] args) {            varquery = fromDefectinchsampledata.alldefectswhereDefect. status==status.closed Join Subscriptioninchsampledata.allsubscriptions on defect. Project equals subscription. ProjectSelect New{defect. Summary, subscription.            EmailAddress}; foreach(varIteminchquery) {Console.WriteLine ($"{item. Emailaddress}-{item. Summary}");        } console.readkey (); }

We can also execute a similar query on the sequence to the right of the join, but it's a little cumbersome:

Static voidMain (string[] args) {            varquery = fromSubscriptioninchsampledata.allsubscriptions Join Defectinch( fromDefectinchsampledata.alldefectswhereDefect. Status = =status.closedSelectdefect) on subscription. Project equals defect. ProjectSelect New{Subscription. EmailAddress, defect.            Summary}; foreach(varIteminchquery) {Console.WriteLine ($"{item. Emailaddress}-{item. Summary}");        } console.readkey (); }

is the description inner join useful in LINQ to objects? SQL always uses an inner join. They are actually a way to navigate from one entity to an associated entity, usually by joining the foreign key of a table with the primary key of another table. In the object-oriented model, we tend to navigate from one object to another by reference. For example, in SQL, you want to get a summary of the flaw and the user name that handles the flaw (the nouns here are properties of objects that are written for code) and need to be joined-in C #, we use the attribute chain. If there is a reverse association in our model, from the Project object to the list of Notificationsubscription objects associated with it, we do not have to use joins to achieve the goal of this example. This is not to say that inline is useless in an object-oriented model-just not so frequently in a relational model.

The results of the inline translation by the compiler are as follows:

The overloaded signature for LINQ to object is as follows:

As the meaning of inner and outer has just been explained, it is omitted here.

When the join is not followed by a SELECT clause, the C#3 compiler introduces a transparent identifier so that the range variable used for both sequences can be used for subsequent clauses, and an anonymous type is created, simplifying the mapping used for the resultselector parameter. However, if the next part of the query expression is a SELECT clause, the projection of the SELECT clause is directly used as the Resultselector parameter--When you can complete these transformations in one step, it is meaningless to create an element pair and then call Select. You can still think of it as the "join" step followed by the "select" step, although both are compressed into a separate method call. In my opinion, this is more consistent in thinking patterns, and this mode of thinking is easy to understand. Unless you're going to study the generated code, you can ignore the optimizations that the compiler has done for you. Happily, the next type of join is easy to understand after learning the relevant knowledge of the inner joins.

C # Review notes (4)--c#3: Innovative Ways to write code (query expressions and LINQ to Object (bottom))

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.