Using Where Clauses with LINQ in VB

Introduction

I have a good understanding of XML, but don’t use XPath
that often. I can command write queries against Active
Directory, but have to look up the syntax because I do it
infrequently. I have been using SQL in its various forms for
more than a decade, so writing SQL queries, except in a few
cases is something I can do adroitly. And, when it comes to
querying objects in code I have the most experience, having
re-written dozens of algorithms long before they were part
of the framework. All of these conflicting skill sets
represent part of the problem: programming today has up
until now required too many disparate skill sets. Having to
focus on how to accomplish something and not just expressing
a solution makes querying data much harder than it should
be. Enter LINQ.

Only a few times in the past–when I did a stint with
Microsoft Consulting–have I been part of the internal
discussions for Microsoft technologies, discussions about
the motivation behind creating a new technology.
Unfortunately, besides from very helpful discussions with
people like Tim Ng and Charlie Calvert, I wasn’t privy to
the early discussions about LINQ. One can make a reasonable
guess though-too many ways to query data, too many skill
sets, and too much inconsistency. LINQ was invented to make
it easier to express what you want to accomplish and less on
how or the underlying technology.

The result is LINQ. LINQ in its simplest form is
basically very similar to an inverted SQL query–with select
coming last–but there are several intricacies that it is
helpful to know about. In this article I am focusing on the
WHERE clause, including how it evolved and how
you can apply it in LINQ queries.

Understanding the Origins of the Where Clause

Interfaces like IEnumerable and IEnumerable(Of T) are
sealed interfaces, and generally interfaces aren’t suppose
to change because any change would be a breaking change. As
a solution extension methods were invented (or introduced
into .NET). There are some 1,000 programming languages, so
extension methods may have been introduced in some earlier
language like Modula-2, LOOPS, Flavors, or SmallTalk but
.NET was where I first heard about them.

An extension method is basically a static method in a
static class. The first argument defines the type being
extended and the compiler resolves an extension method as if
it were a member–of the type being extended. Extension
methods in a nutshell are a way to extend an existing type
without actually modifying that type. Extension methods are
compiler-resolution magic.

The method Where was originally introduced as an
extension method for types that implement IEnumerable(Of T),
such as a collection or array of something. The basic
Where extension method accepts a generic
delegate or Lambda Expression–a short hand form of the
delegate–with a generic input and a Boolean result. The
second form accepts the input type, an integer representing
the items index, and a Boolean. These can be expressed as an
instance of the generic delegate Func(Of T, Boolean) or
Func(Of T, Integer, Boolean). Listing 1 demonstrates the
Where extension method using the generic delegate Func(Of T,
Boolean).



Sub Listing1()
Dim numbers() As Integer = {1, 2, 3, 4, 5}
Dim test As Func(Of Integer, Boolean) = _
Function(i As Integer) i Mod 2 = 1

Dim odds = numbers.Where(test)

For Each num In odds
Console.WriteLine(num)
Next
Console.ReadLine()

End Sub


Listing 1: Using the Where extension method with the generic delegate Func(Of T, Boolean).

In the example an array of integers is defined. Next, the
generic delegate Func (Of Integer, Boolean) is assigned the
Lambda expression Function (I as Integer) I Mod 2 = 1
followed by the Where extension method called
on the array and the output sent to the console. It is worth
noting that the Lambda expression could be used directly in
the Where method (as shown in Listing 2).


Sub Listing2()
Dim numbers() As Integer = {1, 2, 3, 4, 5}
Dim odds = numbers.Where(Function(i As Integer) i Mod 2 = 1)

For Each num In odds
Console.WriteLine(num)
Next
Console.ReadLine()

End Sub


Listing 2: Code that behaves identically to Listing 1 with the Lambda expression used directly in the Where method.

Lambda expressions are simply short hand function
notation, used for convenience in places like
Where extension methods. For more on Lambda
expressions see my book LINQ Unleashed for C# or
Professional DevExpress ASP.NET Controls. Both books have
several examples of LINQ expressions and a discussion of
Lambda expressions (Both books are in C#; while the syntax
is different the concepts are the same).

Using Where with a Single Predicate

In LINQ the Where clause uses a syntax
similar to a SQL statement. When you write a
Where clause in LINQ the compiler converts it
to a Where extension method call. The argument
or arguments to a Where clause have to evaluate
to a Boolean expression and can be referred to as predicates
or expressions (I will use either expression, based on which
sounds the best in a particular sentence).

Where clauses can have a single predicate, multiple
predicates formulated with a combination of And
or Or operators, or multiple Where
clauses. Listing 3 is a revision of Listing 2. Listing 3
converts the direct use of the Where extension
method with its implicit use in a LINQ query.


Sub Listing3()
Dim numbers() As Integer = {1, 2, 3, 4, 5}

Dim odds = From number In numbers _
Where number Mod 2 = 1 _
Select number

For Each num In odds
Console.WriteLine(num)
Next
Console.ReadLine()

End Sub


Listing 3: A LINQ query that obtains the odd numbered integers.

In the example, the Where clause has a
single predicate-number Mod 2 = 1. When the value in the
query is odd it ends up in the result set.

I don’t have a crystal ball, but I can guess what you
might be thinking: numbers. Where is a lot
shorter and simper than the LINQ query shown in Listing 3.
In this instance you would be correct. The difficulty in
writing lengthy queries using all extension methods is that
the results become very challenging to read and write the
more complex the queries get. Use LINQ and let the compiler
code-generate the extension method calls.

More by Author

Must Read