Anonymous types are useful only in the context of the method in which they are declared。 The variable points in the CountCustomers2() method is a collection of anonymous…type objects that could be iterated as follows: For Each customer in points Console。WriteLine(〃Customer (〃 & _ customer。identifier & 〃)(〃 & _ customer。points & 〃)〃) Next The piler that translates the LINQ expression knows that the final result set contains anonymous…type objects with the properties identifier and points。 Processing Multiple Streams In all of the LINQ examples so far; a single result set has been manipulated; processed; and filtered。 You can process multiple inputs at the same time; but you will get a binatorial type answer。 For example; suppose you had this LINQ: Dim set1 As Integer() = New Integer() {1; 2; 3; 4; 5} Dim set2 As Integer() = New Integer() {1; 2; 3; 4; 5} Dim set3 As Integer() = New Integer() {1; 2; 3; 4; 5} Dim triples = _ From a In set1 _ From b In set2 _ From c In set3 _ Select New With {a; b; c} In pseudo…code; the following would be identical。 …………………………………………………………Page 433…………………………………………………………… CH AP T E R 1 5 ■ L E A R N I N G A B OU T L I N Q 411 Dim items As List (Of Object) = New List(Of Object)() For Each a In set1 For Each b In set2 For Each c In set3 items。Add(New With { a; b; c }) Next Next Next When you specify multiple From clauses; you are creating a looping mechanism where each item is iterated against the other elements。 This sounds useful; but it can have a disastrous side effect: a seemingly innocent query can take much longer than it should。 After having written the individual From statements; you can use Where and Select as usual。 Sorting the Results After having selected elements; you will probably want to sort the result set。 Using LINQ; you can sort by anything you deem important。 The obvious approach is to sort according to a number or letter; but you could also sort according to length of the word。 Regardless of how you sort; in LINQ you use the keywords Order By or the method OrderBy()。 The following is a LINQ example that does an alphabetic sort。 Dim words As String() = { 〃cherry〃; 〃apple〃; 〃blueberry〃 } Dim sortedWords = _ From w In words _ Order By w _ Select w The phrase Order By is inserted before Select。 In this case; it will sort the words in ascending alphabetical order。 The way that the Order By works is that the value of the variable is pared; rather than the actual variable。If you want to sort in reverse order; you can use the keyword Descending; as follows: Dim sortedWords = _ From w In words _ Order By w Descending _ Select w This approach allows you to perform sorts according to other values。 For example; you could sort by the length of word; like this: Dim sortedWords = _ From w In words _ Order By w。Length _ Select w …………………………………………………………Page 434…………………………………………………………… 412 CH AP T E R 1 5 ■ L E A R N I N G A B OU T L I N Q The Order By queries for the value of w。Length; which returns a number。 If that number happens to be longer or shorter than another word; it is placed after or before the other word。 You could also sort according to multiple criteria。 For example; you could sort the words alphabetically and then by length: Dim sortedWords = _ From w In words _ Order By w; w。Length _ Select w To sort by multiple criteria; append them to the Order By keywords; each separated by a ma。 ■Note The alphabetical and length sort is fruitless; because when you sort alphabetically; you will auto matically sort by length。 The example is just for illustrative purposes。 Performing Set Operations The last major topic that you need to know about when using LINQ is the ability to perform set operations on a collection。 The major downside; however; to performing set operations is that you must use the methods; and at the time of this writing; no LINQ mand syntax existed for set operations。 Knowing about set operations is useful because they enable you to sort and organize multiple result sets。 The examples in this section involve the Customer type again。 However; to make sure that the set operations function properly; you need to implement the Equals() and GetHashCode() methods; like this: Friend Class Customer Public Overrides Function Equals(ByVal obj As Object) As Boolean If TypeOf obj Is Customer Then Dim otherObj As Customer = TryCast(obj; Customer) If otherObj。Identifier。pareTo(Identifier) = 0 Then Return True End If End If Return False End Function Public Overrides Function GetHashCode() As Integer Return Identifier。GetHashCode() End Function Public Overrides Function ToString() As String Return String。Concat(New Object() _ {〃Ide