TheDeveloperBlog.com


VB.NET LINQ Examples: Queries, Extensions

LINQ. This stands for Language Integrated Query. We import the System.Linq namespace. This provides many extension methods, ones that act on collections.


It allows queries. In a query expression, we describe a command in terms of the desired result. So we can say "get all items greater than 10" rather than use a loop.


A query. This example uses a query expression. The "result" Dim is assigned to a query's result: it uses a special syntax form. It examines all array elements, naming each "v."

Where: It then uses the Where keyword to filter elements. It only accepts elements greater than or equal to 10.

So: When we evaluate the "result" value in our For-Each loop, we see only the elements that the query selected. These are 10 and 100.

For Each
Based on:

.NET 4.5

VB.NET program that uses query

Imports System.Linq

Module Module1
    Sub Main()

	' An array of four elements.
	Dim values() As Integer = {1, 10, 100, 5}

	' Gets all values greater than 9.
	Dim result = From v In values Where v >= 10

	' Display all matching Integers.
	For Each value As Integer In result
	    Console.WriteLine(value)
	Next

    End Sub
End Module

Output

10
100

Order By. With Order By we can sort the results of a query. This statement comes after other query clauses like "Where." By default it is Ascending, ordering from low to high.

VB.NET program that uses Order By

Imports System.Linq

Module Module1
    Sub Main()

	Dim values() As Integer = {3, 10, -1, 30, -3}

	' Order the elements from low to high (ascending).
	Dim result = From v In values Order By v

	For Each value As Integer In result
	    Console.WriteLine(value)
	Next

    End Sub
End Module

Output

-3
-1
3
10
30

Descending. We can apply the Descending keyword to an Order By clause in a query expression. This orders the elements from last to first (for strings, "Z" to "A").

Tip: For numbers, Descending orders from largest to smallest. Strings use a reverse alphabetical sort.

VB.NET program that uses order by, descending

Imports System.Linq

Module Module1
    Sub Main()

	Dim animals() As String = {"cat", "turtle", "ant"}

	' Sort animals alphabetically, last to first.
	Dim result = From a In animals
		     Order By a Descending

	For Each value As String In result
	    Console.WriteLine(value)
	Next

    End Sub
End Module

Output

turtle
cat
ant

Group By, Into. With a query, we can also group elements together into automatically-generated groups. The syntax is confusing. We use the "Group" keyword twice—once for naming the group.

By: After By, we specify the property that will be used to separate groups (here I use Item1, part of the tuples).

Tuple

Into: In this part of the Group clause, we assign an identifier to the group—it can be any valid identifier (I use "TupleGroup").

TupleGroup: Each group contains a collection called TupleGroup (named in the program). We loop over it to display all values.

VB.NET program that uses Group, By, Into

Module Module1

    Sub Main()

	' Create list of tuples with two items each.
	Dim list = New List(Of Tuple(Of Integer, String))
	list.Add(New Tuple(Of Integer, String)(5, "green"))
	list.Add(New Tuple(Of Integer, String)(5, "blue"))
	list.Add(New Tuple(Of Integer, String)(20, "orange"))
	list.Add(New Tuple(Of Integer, String)(20, "yellow"))
	list.Add(New Tuple(Of Integer, String)(20, "magenta"))

	' Group tuples by their first item.
	' ... TupleGroup is an identifier name.
	Dim result = From v In list
		     Group v By v.Item1 Into TupleGroup = Group

	' Loop over each group and its items.
	For Each value In result
	    Console.WriteLine(value.Item1)
	    For Each item In value.TupleGroup
		Console.WriteLine("    " + item.Item2)
	    Next
	Next

    End Sub

End Module

Output

5
    green
    blue
20
    orange
    yellow
    magenta

Extensions. The System.Linq namespace also gives us many extension methods. In VB.NET we do not need to import the System.Linq namespace to use these extensions.

Extension Method

Tip: These extensions, like Average(), act upon any collection of type IEnumerable. An array, List, or query result qualifies.

ArraysListIEnumerable

Here: We use Average to compute the average number in an array of four Integers. The average, a Double, happens to equal 5.

VB.NET program that uses average extension

Module Module1
    Sub Main()
	Dim numbers() As Integer = {2, 4, 6, 8}

	' Use the Average extension from System.Linq.
	Dim average As Double = numbers.Average()
	Console.WriteLine(average)
    End Sub
End Module

Output

5

Chain extensions. Extension methods, like those found in LINQ, often return the results of their invocation. So we can call further extensions on them.

Here: Take() returns the first three elements, in an IEnumerable collection. So Average() can be invoked on its result.

VB.NET program that chains extension methods

Module Module1

    Sub Main()
	Dim elements() As Integer = {5, 10, 15, 20, 25}

	' Take first three numbers and average them.
	Dim averageFirstThree = elements.Take(3).Average()
	Console.WriteLine(averageFirstThree)
    End Sub

End Module

Output

10

Any extension, lambda. The Any method returns True if the condition evaluates to True for any element in a sequence. This extension method can be used with a lambda expression.

Lambdas
VB.NET that uses Any, Func

Module Module1

    Sub Main()
	Dim values() As Integer = {10, -200, 1, 30, -1}

	' See if the array has a negative number.
	Dim hasNegative = values.Any(Function(x As Integer)
					 Return x < 0
				     End Function)
	Console.WriteLine(hasNegative)
    End Sub

End Module

Output

True

Query and extension call. We can combine query syntax with extension method calls. Consider this example—it orders the numbers with a query expression (Order By).

Then: It uses the Take() extension upon the result of the query expression. This style is sometimes useful.

VB.NET that uses query, extension method

Imports System.Linq

Module Module1
    Sub Main()

	Dim numbers() As Integer = {5, 10, 1}

	' Take first two numbers from ordered query.
	Dim result = (From n In numbers
		      Order By n).Take(2)

	For Each value As Integer In result
	    Console.WriteLine(value)
	Next

    End Sub
End Module

Output

1
5

ToArray, ToList. Some extension methods from System.Linq convert collections. With ToArray and ToList, we convert from an IEnumerable to an array or List. Many types implement IEnumerable.

ToArrayToList

System.Xml.Linq. The System.Xml.Linq namespace contains the XElement type. With XElement we can load XML, even from the network, and query it with LINQ.

XElement

Useful. Many VB.NET programs need no LINQ features: query expressions and extensions are not always useful. But these features have power. They make some programs shorter, easier to read.


Performance. Often LINQ features do not lead to the best performance. Using iterative statements, like for loops, and maintaining state in local variables is often faster.