574
Part I: The C# Language
In this form, sort-onA is the item on which the primary sorting is done. Then, each group of 
equivalent items is sorted on sort-onB, and each of those groups is sorted on sort-onC, and so 
on.Thus, each subsequent sort-on specifies a “then by” item on which to sort. In all cases, 
direction is optional, defaulting to ascending. Here is an example that uses three sort criteria 
balance:
// Sort on multiple criteria with orderby.
using System;
using System.Linq;
class Account {
public string FirstName { get; private set; }
public string LastName { get; private set; }
public double Balance { get; private set; }
public string AccountNumber { get; private set; }
public Account(string fn, string ln, string accnum, double b) {
FirstName = fn;
LastName = ln;
AccountNumber = accnum;
Balance = b;
}
}
class OrderbyDemo {
static void Main() {
// Create some data.
};
// Create a query that obtains the accounts in sorted order.
// by first name, and finally by account balance.
var accInfo = from acc in accounts
orderby acc.LastName, acc.FirstName, acc.Balance
select acc;
Split pdf into multiple files - Merge, append PDF files in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Provide C# Demo Codes for Merging and Appending PDF Document
pdf combine files online; pdf mail merge
Split pdf into multiple files - VB.NET PDF File Merge Library: Merge, append PDF files in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET Guide and Sample Codes to Merge PDF Documents in .NET Project
pdf combine; apple merge pdf
P
A
R
T
I
Chapter 19: LINQ 
575
P
A
R
T
I
P
A
R
T
I
Console.WriteLine("Accounts in sorted order: ");
string str = "";
// Execute the query and display the results.
foreach(Account acc in accInfo) {
if(str != acc.FirstName) {
Console.WriteLine();
str = acc.FirstName;
}
Console.WriteLine("{0}, {1}\tAcc#: {2}, {3,10:C}",
acc.LastName, acc.FirstName,
acc.AccountNumber, acc.Balance);
}
Console.WriteLine();
}
}
The output is shown here:
Accounts in sorted order:
Jones, Jenny       Acc#: 108CK,     $10.98
Jones, Ralph       Acc#: 434CK,  ($123.32)
Jones, Ralph       Acc#: 454MM,    $987.13
Jones, Ralph       Acc#: 436CD,  $1,923.85
Krammer, Betty     Acc#: 968MM,  $5,146.67
Krammer, Ted       Acc#: 897CD,  $3,223.19
Smith, Albert      Acc#: 445CK,  ($213.67)
Smith, Carl        Acc#: 078CD, $15,345.99
Smith, Sara        Acc#: 843CK,    $345.00
Smith, Sara        Acc#: 543MM,  $5,017.40
Smith, Sara        Acc#: 547CD, $34,955.79
Smith, Tom         Acc#: 132CK,    $100.23
Smith, Tom         Acc#: 132CD, $10,000.00
In the query, look closely at how the orderby clause is written:
var accInfo = from acc in accounts
orderby acc.LastName, acc.FirstName, acc.Balance
select acc;
Here is how it works. First, the results are sorted by last name, and then entries with the 
same last name are sorted by the first name. Finally, groups of entries with the same first 
C# PDF File Split Library: Split, seperate PDF into multiple files
outputFiles); Split PDF Document into Multiple PDF Files in C#. You can use the following C# demo to split PDF document to four files.
merge pdf online; add two pdf files together
VB.NET PDF File Split Library: Split, seperate PDF into multiple
Split PDF file into two or multiple files in ASP.NET webpage online. Split PDF Document into Multiple PDF Files Demo Code in VB.NET.
pdf merge files; all jpg to one pdf converter
576
Part I: The C# Language
and last name ar
name Jones is shown in this order:
Jones, Jenny       Acc#: 108CK,     $10.98
Jones, Ralph       Acc#: 434CK,  ($123.32)
Jones, Ralph       Acc#: 454MM,    $987.13
Jones, Ralph       Acc#: 436CD,  $1,923.85
account balance.
When using multiple criteria, you can reverse the condition of any sort by applying 
thedescending option. For example, this query causes the results to be shown in order 
of decreasing balance:
var accInfo = from acc in accounts
orderby x.LastName, x.FirstName, x.Balance descending
select acc;
Jones, Jenny       Acc#: 108CK,     $10.98
Jones, Ralph       Acc#: 436CD,  $1,923.85
Jones, Ralph       Acc#: 454MM,    $987.13
Jones, Ralph       Acc#: 434CK,  ($123.32)
As you can see, now the accounts for Ralph Jones are displayed from greatest to least.
A Closer Look at select
Theselect clause determines what type of elements are obtained by a query. Its general 
form is shown here:
selectexpression
So far we have been using select to return the range variable. Thus, expression has simply 
named the range variable. However, select is not limited to this simple action. It can return 
a specific portion of the range variable, the result of applying some operation or transformation 
to the range variable, or even a new type of object that is constructed from pieces of the 
information retrieved from the range variable. This is called projecting.
To begin examining the other capabilities of select, consider the following program. It 
displays the square roots of the positive values contained in an array of double values.
// Use select to return the square root of all positive values
// in an array of doubles.
using System;
using System.Linq;
class SelectDemo {
static void Main() {
Online Split PDF file. Best free online split PDF tool.
Easy split! We try to make it as easy as possible to split your PDF files into Multiple ones. You can receive the PDF files by simply
add multiple pdf files into one online; split pdf into multiple files
C# PDF Page Insert Library: insert pages into PDF file in C#.net
the ability to inserting a new PDF page into existing PDF PDF page using C# .NET, how to reorganize PDF document pages and how to split PDF document in
pdf combine two pages into one; c# merge pdf pages
P
A
R
T
I
Chapter 19: LINQ 
577
P
A
R
T
I
P
A
R
T
I
// Create a query that returns the square roots of the
// positive values in nums.
var sqrRoots = from n in nums
where n > 0
select Math.Sqrt(n);
Console.WriteLine("The square roots of the positive values" +
" rounded to two decimal places:");
// Execute the query and display the results.
foreach(double r in sqrRoots) Console.WriteLine("{0:#.##}", r);
}
}
The output is shown here:
The square roots of the positive values rounded to two decimal places:
4.05
3.48
10.04
5.02
In the query, pay special attention to the select clause:
select Math.Sqrt(n);
It returns the square root of the range variable. It does this by obtaining the result of passing 
the range variable to Math.Sqrt( ), which returns the square root of its argument. This means 
e roots of the 
positive values in nums. If you generalize this concept, the power of select becomes apparent. 
You can use select
from the data source.
Here is a program that shows another way to use select. It creates a class called 
EmailAddress that contains two properties. The first holds a person’s name. The second 
contains an e-mail address. The program then creates an array that contains several 
EmailAddress entries. The program uses a query to obtain a list of just the e-mail 
addresses by themselves.
// Return a portion of the range variable.
using System;
using System.Linq;
class EmailAddress {
public string Name { get; set; }
public string Address { get; set; }
public EmailAddress(string n, string a) {
Name = n;
Address = a;
}
}
VB.NET PDF Convert to Jpeg SDK: Convert PDF to JPEG images in vb.
Images. File & Page Process. File: Merge, Append PDF Files. File: Split PDF Document. Turn multiple pages PDF into multiple jpg files in VB.NET class.
merge pdf online; append pdf files reader
VB.NET TWAIN: Scanning Multiple Pages into PDF & TIFF File Using
This VB.NET TWAIN pages scanning control add-on is developed to offer programmers an efficient solution to scan multiple pages into one PDF or TIFF
adding pdf pages together; all jpg to one pdf converter
578
Part I: The C# Language
class SelectDemo2 {
static void Main() {
EmailAddress[] addrs = {
new EmailAddress("Herb", "Herb@HerbSchildt.com"),
new EmailAddress("Tom", "Tom@HerbSchildt.com"),
new EmailAddress("Sara", "Sara@HerbSchildt.com")
};
// Create a query that selects e-mail addresses.
var eAddrs = from entry in addrs
select entry.Address;
Console.WriteLine("The e-mail addresses are");
// Execute the query and display the results.
foreach(string s in eAddrs) Console.WriteLine("  " + s);
}
}
The output is shown here:
The e-mail addresses are
Herb@HerbSchildt.com
Tom@HerbSchildt.com
Sara@HerbSchildt.com
Pay special attention to the select clause:
select entry.Address;
Instead of returning the entire range variable, it returns only the Address portion. This 
fact is evidenced by the output. This means the query returns a sequence of strings, not a 
sequence of EmailAddress objects. This is why the foreach loop specifies s as a string. As 
explained, the type of sequence returned by a query is determined by the type of value 
returned by the select clause.
One of the more powerful features of select is its ability to return a sequence that contains 
elements created during the execution of the query. For example, consider the following 
program. It defines a class called ContactInfo, which stores a name, e-mail address, and 
telephone number. It also defines the EmailAddress class used by the preceding example. 
InsideMain( ), an array of ContactInfo is created. Then, a query is declared in which the 
data source is an array of ContactInfo, but the sequence returned contains EmailAddress
objects. Thus, the type of the sequence returned by select is not ContactInfo, but rather 
EmailAddress, and these objects are created during the execution of the query.
// Use a query to obtain a sequence of EmailAddresses
// from a list of ContactInfo.
using System;
using System.Linq;
class ContactInfo {
public string Name { get; set; }
public string Email { get; set; }
C# PDF: C#.NET PDF Document Merging & Splitting Control SDK
C#.NET PDF Splitter to Split PDF File. In this section, we aims to tell you how to divide source PDF file into two smaller PDF documents at the page
pdf merge; pdf merger
VB.NET PDF Library SDK to view, edit, convert, process PDF file
Simply integrate into VB.NET project, supporting conversions to or from multiple supported images formats; merge, append, and split PDF files; insert, delete
acrobat combine pdf files; combine pdfs online
P
A
R
T
I
Chapter 19: LINQ 
579
P
A
R
T
I
P
A
R
T
I
public string Phone { get; set; }
public ContactInfo(string n, string a, string p) {
Name = n;
Email = a;
Phone = p;
}
}
class EmailAddress {
public string Name { get; set; }
public string Address { get; set; }
public EmailAddress(string n, string a) {
Name = n;
Address = a;
}
}
class SelectDemo3 {
static void Main() {
ContactInfo[] contacts = {
new ContactInfo("Herb", "Herb@HerbSchildt.com", "555-1010"),
new ContactInfo("Tom", "Tom@HerbSchildt.com", "555-1101"),
new ContactInfo("Sara", "Sara@HerbSchildt.com", "555-0110")
};
// Create a query that creates a list of EmailAddress objects.
var emailList = from entry in contacts
select new EmailAddress(entry.Name, entry.Email);
Console.WriteLine("The e-mail list is");
// Execute the query and display the results.
foreach(EmailAddress e in emailList)
Console.WriteLine("  {0}: {1}", e.Name, e.Address );
}
}
The output is shown here:
The e-mail list is
Herb: Herb@HerbSchildt.com
Tom: Tom@HerbSchildt.com
Sara: Sara@HerbSchildt.com
In the query, pay special attention to the select clause:
select new EmailAddress(entry.Name, entry.Email);
It creates a new EmailAddress object that contains the name and e-mail address obtained 
from a ContactInfo object in the contacts array. The key point is that new EmailAddress
objects are created by the query in its select clause, during the query’s execution.
580
Part I: The C# Language
Use Nested from Clauses
A query can contain more than one from clause. Thus, a query can contain nested from
clauses. One common use of a nested from clause is found when a query needs to obtain 
data from two different sources. Here is a simple example. It uses two from clauses to 
iterate over two different character arrays. It produces a sequence that contains all possible 
combinations of the two sets of characters.
// Use two from clauses to create a list of all
// possible combinations of the letters A, B, and C
// with the letters X, Y, and Z.
using System;
using System.Linq;
// This class holds the result of the query.
class ChrPair {
public char First;
public char Second;
public ChrPair(char c, char c2) {
First = c;
Second = c2;
}
}
class MultipleFroms {
static void Main() {
char[] chrs = { 'A', 'B', 'C' };
char[] chrs2 = { 'X', 'Y', 'Z' };
// Notice that the first from iterates over chrs and
// the second from iterates over chrs2.
var pairs = from ch1 in chrs
from ch2 in chrs2
select new ChrPair(ch1, ch2);
Console.WriteLine("All combinations of ABC with XYZ: ");
foreach(var p in pairs)
Console.WriteLine("{0} {1}", p.First, p.Second);
}
}
The output is shown here:
All combinations of ABC with XYZ:
A X
A Y
A Z
B X
B Y
P
A
R
T
I
Chapter 19: LINQ 
581
P
A
R
T
I
P
A
R
T
I
B Z
C X
C Y
C Z
The program begins by creating a class called ChrPair that will hold the results of the 
query. It then creates two character arrays, called chrs and chrs2. It uses the following query 
to produce all possible combinations of the two sequences:
var pairs = from ch1 in chrs
from ch2 in chrs2
select new ChrPair(ch1, ch2);
The nested from clauses cause both chrs and chrs2 to be iterated over. Here is how it works. 
First, a character is obtained from chrs and stored in ch1. Then, the chrs2 array is enumerated. 
With each iteration of the inner from, a character from chrs2 is stored in ch2 and the select
clause is executed. The result of the select clause is a new object of type ChrPair that contains 
the character pair ch1,ch2 produced by each iteration of the inner from. Thus, a ChrPair is 
produced in which each possible combination of characters is obtained.
Another common use of a nested from is to iterate over a data source that is contained 
within another data source. An example of this is found in the section, “Use let to Create 
a Variable in a Query,” later in this chapter.
Group Results with group
One of the most powerful query features is provided by the group clause because it enables 
you to create results that are grouped by keys. Using the sequence obtained from a group, 
you can easily access all of the data associated with a key. This makes group an easy and 
effective way to retrieve data that is organized into sequences of related items. The group
clause is one of only two clauses that can end a query. (The other is select.)
Thegroup clause has the following general form:
group range-variable by key
It returns data grouped into sequences, with each sequence sharing the key specified by key.
The result of group is a sequence that contains elements of type IGrouping<TKey, 
TElement>, which is declared in the System.Linq namespace. It defines a collection of 
objects that share a common key. The type of query variable in a query that returns a group 
isIEnumerable<IGrouping<TKey, TElement>>.IGrouping defines a read-only property 
calledKey, which returns the key associated with each sequence.
Here is an example that illustrates the use of group. It declares an array that contains a 
list of websites. It then creates a query that groups the list by top-level domain name, such 
as.org or .com.
// Demonstrate the group clause.
using System;
using System.Linq;
class GroupDemo {
static void Main() {
582
Part I: The C# Language
string[] websites = { "hsNameA.com", "hsNameB.net", "hsNameC.net",
"hsNameD.com", "hsNameE.org", "hsNameF.org",
"hsNameG.tv",  "hsNameH.net", "hsNameI.tv" };
// Create a query that groups websites by top-level domain name.
var webAddrs = from addr in websites
where addr.LastIndexOf('.') != -1
// Execute the query and display the results.
foreach(var sites in webAddrs) {
Console.WriteLine("Web sites grouped by " + sites.Key);
foreach(var site in sites)
Console.WriteLine("  " + site);
Console.WriteLine();
}
}
}
The output is shown here:
Web sites grouped by .com
hsNameA.com
hsNameD.com
Web sites grouped by .net
hsNameB.net
hsNameC.net
hsNameH.net
Web sites grouped by .org
hsNameE.org
hsNameF.org
Web sites grouped by .tv
hsNameG.tv
hsNameI.tv
As the output shows, the data is grouped based on the top-level domain name of a 
website. Notice how this is achieved by the group clause:
var webAddrs = from addr in websites
where addr.LastIndexOf('.') != -1
group addr by addr.Substring(addr.LastIndexOf('.'));
The key is obtained by use of the LastIndexOf( ) and Substring( ) methods defined by string.
(These are described in Chapter 7. The version of Substring( ) used here returns the substring 
that starts at the specified index and runs to the end of the invoking string.) The index of the 
last period in a website name is found using LastIndexOf( ). Using this index, the Substring( )
method obtains the remainder of the string, which is the part of the website name that 
where clause to 
filter out any strings that don’t contain a period. The LastIndexOf( ) method returns –1 if 
the specified string is not contained in the invoking string.
P
A
R
T
I
Chapter 19: LINQ 
583
P
A
R
T
I
P
A
R
T
I
Because the sequence obtained when webAddrs is executed is a list of groups, you will 
need to use two foreach loops to access the members of each group. The outer loop obtains 
each group. The inner loop enumerates the members within the group. The iteration variable 
of the outer foreach loop must be an IGroupinginstancecompatible with the key and 
element type. In the example both the keys and elements are string. Therefore, the type of 
thesites iteration variable of the outer loop is IGrouping<string, string>. The type of the 
iteration variable of the inner loop is string. For brevity, the example implicitly declares 
these variables, but they could have been explicitly declared as shown here:
foreach(IGrouping<string, string> sites in webAddrs) {
Console.WriteLine("Web sites grouped by " + sites.Key);
foreach(string site in sites)
Console.WriteLine("  " + site);
Console.WriteLine();
}
Use into to Create a Continuation
When using select or group, you will sometimes want to generate a temporary result that 
will be used by a subsequent part of the query to produce the final result. This is called a 
querycontinuation (or just a continuation for short), and it is accomplished through the use 
ofinto with a select or group clause. It has the following general form:
intoname query-body
where name is the name of the range variable that iterates over the temporary result and is 
used by the continuing query, specified by query-body. This is why into is called a query 
continuation when used with select or group—it continues the query. In essence, a query 
esults of the 
preceding query.
N
OTE
N
OTE
There is also a form of into that can be used with join, which creates a group join. This is 
described later in this chapter.
Here is an example that uses into with group. The following program reworks the 
GroupDemo example shown earlier, which creates a list of websites grouped by top-level 
domain name. In this case, the initial results are queried by a range variable called ws. This 
result is then filtered to remove all groups that have fewer than three elements.
// Use into with group.
using System;
using System.Linq;
class IntoDemo {
static void Main() {
string[] websites = { "hsNameA.com", "hsNameB.net", "hsNameC.net",
"hsNameD.com", "hsNameE.org", "hsNameF.org",
"hsNameG.tv",  "hsNameH.net", "hsNameI.tv" };
Documents you may be interested
Documents you may be interested