Introducing LINQ for Visual Basic, Page 2
Using Ordering Clauses in LINQ
Listing 2 defines an unordered array of Fibonacci numbers and uses an ORDER clause to order the array. (Google Fibonacci for a definition. You will find these numbers pretty interesting.)
Listing 2: Ordering an Array of Integers Using LINQ
Sub SampleTwo()
Dim numbers = {2, 1, 34, 5, 8, 13, 21, 3}
Dim ordered = From num In numbers _
Select num _
Order By num
For Each Dim n In ordered
Console.WriteLine(n)
Next
Console.ReadLine()
End Sub
Listing 2 is like Listing 1 but with the addition of the Order By clause. The anonymous type ordered contains the re-ordered list of integers: 1, 2, 3, 5, 8, 13, 21, 34. Adding the keyword Descending after the clause Order By num will sort the list in reverse order. This variant is shown in Listing 3.
Listing 3: Sorting in Reverse Order
Sub SampleThree()
Dim numbers = {2, 1, 34, 5, 8, 13, 21, 33}
Dim ordered = From num In numbers _
Select num _
Order By num Descending
For Each Dim n In ordered
Console.WriteLine(n)
Next
Console.ReadLine()
End Sub
Sorting Generic Lists of Custom Types
You can also apply LINQ to custom types. Suppose I define a custom type Customer (see Listing 4) and want to sort a generic list of customers.
Listing 4: A User-Defined Customer Class
Public Class Customer
Private fid As Integer
Private fname As String
Private fcity As String
Public Sub New(ByVal id As Integer, ByVal name As String, _
ByVal city As String)
fid = id
fname = name
fcity = city
End Sub
Public Overrides Function toString() As String
Dim mask As String = "{0} is in {1}"
Return String.Format(mask, fname, fcity)
End Function
Public Property ID() As Integer
Get
Return fid
End Get
Set(ByVal value As Integer)
fid = value
End Set
End Property
Public Property Name() As String
Get
Return fname
End Get
Set(ByVal value As String)
fname = value
End Set
End Property
Public Property city() As String
Get
Return fcity
End Get
Set(ByVal value As String)
fcity = value
End Set
End Property
End Class
I can define the Customer class and instantiate a List(Of T) where T is a customer using a specific field from the class Customer (see Listing 5).
Listing 5: Initializing a Generic List of Customer Objects and Sorting Based on the City Field
Sub SampleFour()
Dim customers = New List(Of Customer)
customers.Add(New Customer(1, "Kimmel Computers", "Plattsburgh"))
customers.Add(New Customer(2, "Fred's Frieds", "Memphis"))
customers.Add(New Customer(3, "House of Clams", "Detroit"))
Dim ordered = From cust In customers _
Select cust _
Order By cust.City
For Each Dim c In ordered
Console.WriteLine(c.toString())
Next
Console.ReadLine()
End Sub
Implementing IComparable
If you modify Customer by implementing Icomparable, you can tell Customer objects how to compare themselves. Implement IComparable by adding the Implements IComparable statement to the Custom class and adding the Function CompareTo. Listing 6 shows the revised Customer class, and Listing 7 shows the revised code from Listing 5 that now uses LINQ to sort based on the implementation of IComparable.
Listing 6: Implement IComparable to Compare Customer Objects by City
Public Class Customer
Implements IComparable
Private fid As Integer
Private fname As String
Private fcity As String
Public Sub New(ByVal id As Integer, ByVal name As String, _
ByVal city As String)
fid = id
fname = name
fcity = city
End Sub
Public Overrides Function toString() As String
Dim mask As String = "{0} is in {1}"
Return String.Format(mask, fname, fcity)
End Function
Public Property ID() As Integer
Get
Return fid
End Get
Set(ByVal value As Integer)
fid = value
End Set
End Property
Public Property Name() As String
Get
Return fname
End Get
Set(ByVal value As String)
fname = value
End Set
End Property
Public Property city() As String
Get
Return fcity
End Get
Set(ByVal value As String)
fcity = value
End Set
End Property
Public Function CompareTo(ByVal obj As Object) _
As Integer Implements System.IComparable.CompareTo
Return city.CompareTo(obj.City)
End Function
End Class
Listing 7: Sorting a Generic List of IComparable Customer Objects
Sub SampleFive()
Dim customers = New List(Of Customer)
customers.Add(New Customer(1, "Kimmel Computers", "Plattsburgh"))
customers.Add(New Customer(2, "Fred's Frieds", "Memphis"))
customers.Add(New Customer(3, "House of Clams", "Detroit"))
Dim ordered = From cust In customers _
Select cust _
Order By cust
For Each Dim c In ordered
Console.WriteLine(c.toString())
Next
Console.ReadLine()
End Sub
The only difference between Listing 7 and Listing 5 is that the Order By clause now specifies that you are sorting only Customer objects. The sort field is implicit as defined by the CompareTo function.
A SQL-Like Query Language
This article introduced LINQ and demonstrated how you can combine this technology with existing technologies such as interfaces and generic lists to support a SQL-like query language in your VB.NET code. Of course, LINQ (and .NET 3.5) introduce many more capabilities, including anonymous types and support for ADO.NET and XML. Go ahead and explore.
About the Author
Paul Kimmel is the VB Today columnist for www.codeguru.com and has written several books on object-oriented programming, including Visual Basic .NET Power Coding (Addison-Wesley) and UML Demystified (McGraw-Hill/Osborne). He is the president and co-founder of the Greater Lansing Area Users Group for .NET (www.glugnet.org) and a Microsoft Visual Developer MVP.
Copyright © 2006 by Paul T. Kimmel. All Rights Reserved.
