Overview of Visual Basic 9.0
Ó
Microsoft Corporation 2005. All Rights Reserved. 1
Overview of Visual Basic 9.0
September 2005
Erik Meijer, Amanda Silver, Paul Vick
Microsoft Corporation
Overview of Visual Basic 9.0
2
Ó
Microsoft Corporation 2005. All Rights Reserved.
1. Overview of VB 9.0
“Visual Basic Orcas” (VB 9.0 ) introduces several language extensions that build on “Visual Basic Whidbey”
(VB 8.0) to support data-intensive programming – creating, updating, and querying relational databases, XML
documents, and object graphs – in a unified way. In addition, VB 9.0 introduces several new language features
to enhance Visual Basic’s unique facility for static typing where possible, and dynamic typing where necessary.
These new features are:
� Implicitly typed local variables
� Query comprehensions
� Object initializers
� Anonymous types
� Full integration with the Linq framework
� Deep XML support
� Relaxed delegates
� Nullable types
� Dynamic interfaces
� Dynamic identifiers
This document is an informal overview of these new features. More information, including updates to the Visual
Basic language definition and compiler previews, is available on the Visual Basic Developer Center
(http://msdn.microsoft.com/vbasic/default.aspx).
1.1 Getting Started With VB 9.0
To see the power of these language features at work, let’s start with a real world example –the CIA World
Factbook database. The database contains a variety of geographic, economic, social, and political information
about the world’s countries. For the sake of our example, we begin with a schema for the name of each country
and its capital, total area, and population. We represent this schema in VB 9.0 using the following class:
Class Country
Public Property Name As String
Public Property Area As Float
Public Property Population As Integer
End Class
Here is a small subset of the country database that we will use as our running example:
Overview of Visual Basic 9.0
Ó
Microsoft Corporation 2005. All Rights Reserved. 3
Dim Countries = _
{ new Country{ _
.Name = "Palau", .Area = 458, .Population = 16952 }, _
new Country{ _
.Name = "Monaco", .Area = 1.9, .Population = 31719 }, _
new Country{ _
.Name = "Belize", .Area = 22960, .Population = 219296 }, _
new Country{ _
.Name = "Madagascar", .Area = 587040, .Population = 13670507 } _
}
Given this list, we can query for all countries whose population is less than one million by using the following
query comprehension:
Dim SmallCountries = Select Country _
From Country In Countries _
Where Country.Population < 1000000
For Each Country As Country In SmallCountries
Console.WriteLine(Country.Name)
Next
Because only Madagascar has more than one million inhabitants, the above program would print the following
list of country names when compiled and run:
Palau
Monaco
Belize
Let’s examine the program to understand the features of Visual Basic 9.0 that made this so simple to write. First
of all, the declaration of the Countries variable
Dim Countries = _
{ new County { .Name = "Palau", .Area = 458, .Population = 16952 }, _
… _
}
uses the new object-initializer syntax new Country {…, .Area = 458, …} to create a complex object
instance through a concise, expression-based syntax similar to the existing With statement.
The declaration also illustrates implicitly typed local-variable declarations, where the compiler infers the type of
the local variable Countries from the initializer expression on the right-hand side of the declaration. The
declaration above is precisely equivalent to an explicitly typed local-variable declaration of type Country().
Dim Countries As Country() = {…}
To repeat, this is still a strongly typed declaration; the compiler has automatically inferred the type of the right-
hand side of the local declaration, and there is no need for the programmer to manually enter that type into the
program.
The local-variable declaration SmallCountries is initialized with a SQL-style query comprehension to filter
out all countries that have fewer than one million inhabitants. The resemblance to SQL is intentional, allowing
programmers who already know SQL to get started with Visual Basic query syntax all the more quickly.
Dim SmallCountries = Select Country _
From Country In Countries _
Where Country.Population < 1000000
Note that we have another application of implicit typing: the compiler infers the type of SmallCountries as
IEnumerable(Of Country). The compiler translates the query comprehension itself into standard query
operators. In this case, the translation could be as simple as the following:
Overview of Visual Basic 9.0
4
Ó
Microsoft Corporation 2005. All Rights Reserved.
Function F(Country As Country) As Boolean
Return Country.Population < 1000000
End Function
Dim SmallCountries As IEnumerable(Of Country) = _
Countries.Where(AddressOf F)
The expanded syntax passes the compiler-generated local function as a delegate AddressOf F to the extension
function Where, which is defined in the standard query operator library as an extension of the
IEnumerable(Of T) interface.
Now that we have seen a few of the new features in Visual Basic 9, let us drill down into a more detailed
overview.
1.2 Implicitly typed local variables
In an implicitly typed local-variable declaration, the type of the local variable is inferred from the initializer
expression on the right-hand side of a local declaration statement. For example, the compiler infers the types of
all the following variable declarations:
Dim Population = 31719
Dim Name = "Belize"
Dim Area = 1.9
Dim Country = New Country{ .Name = "Palau", …}
Hence they are precisely equivalent to the following, explicitly typed declarations:
Dim Population As Integer = 31719
Dim Name As String = "Belize"
Dim Area As Float = 1.9
Dim Country As Country = New Country{ .Name = "Palau", …}
Because types of local-variable declarations are inferred by default, no matter what the setting of Option
Strict is, access to such variables is always early-bound. The programmer must explicitly specify late binding
in VB 9.0, by explicitly declaring variables as of type Object, as follows:
Dim Country As Object = new Country{ .Name = "Palau", … }
Requiring explicit late binding prevents accidentally using late binding and, more importantly, it allows
powerful extensions of of late binding to new data types such as XML, as we will see below. There will be an
optional project-level switch to toggle the existing behaviour.
The loop-control variable in a For…Next or a For Each…Next statement can also be an implicitly typed
variable. When the loop-control variable is specified, as in For Dim I = 0 To Count, or as in For Each
Dim C In SmallCountries, the identifier defines a new, implicitly typed local variable, whose type is
inferred from the initializer or collection expression and is scoped to the entire loop. This use of Dim to the right
of For is new to VB 9.0, as are implicitly typed loop-control variables.
With this application of type inference, we can rewrite the loop that prints all small countries as follows:
For Each Dim Country In SmallCountries
Console.WriteLine(Country.Name)
Next
The type of Country is inferred to be Country, the element type of SmallCountries.
1.3 Object and Collection Initializers
In Visual Basic, the With statement simplifies access to multiple members of an aggregate value without
specifying the target expression multiple times. Inside the With statement block, a member-access expression
Overview of Visual Basic 9.0
Ó
Microsoft Corporation 2005. All Rights Reserved. 5
starting with a period is evaluated as if the period were preceded by the target expression of the With statement.
For example, the following statements initialize a new Country instance and subsequently initializes its fields
to the required values:
Dim Palau = New Country()
With Palau
.Name = "Palau"
.Area = 458
.Population = 16952
End With
VB 9.0’s new object initializers are an expression-based form of With for creating complex object instances
concisely. Using object initializers, we can capture the above two statements into a single (implicitly typed)
local declaration, as follows:
Dim Palau = New Country { _
.Name = "Palau", _
.Area = 458, _
.Population = 16952
}
This style of object initialization from expressions is important for queries. Typically, a query looks like an
object declaration initialized by a Select clause on the right-hand side of the equals sign. Because the Select
clause returns an expression, we must be able to initialize the entire object with a single expression.
As we have seen, object initializers are also convenient for creating collections of complex objects. Any
collection that supports an Add method can be initialized using a collection initializer expression. For instance,
given the declaration for cities as the partial class,
Partial Class City
Public Property Name As String
Public Property Country As String
Public Property Longitude As Float
Public Property Latitude As Float
End Class
we can create a List(Of City) of capital cities of our example countries as follows:
Dim Capitals = New List(Of City){ _
{ .Name = "Antanarivo", _
.Country = "Madagascar", _
.Longitude = 47.4, _
.Lattitude = -18.6 }, _
{ .Name = "Belmopan", _
.Country = "Belize", _
.Longitude = -88.5, _
.Latitude = 17.1 }, _
{ .Name = "Monaco", _
.Country = "Monaco", _
.Longtitude = 7.2, _
.Latitude = 43.7 }, _
{ .Country = "Palau",
.Name = "Koror", _
.Longitude = 135, _
.Latitude = 8 } _
}
This example also uses nested object initialers, where the constructors of the nested initializers are inferred from
the context. In this case, each nested initializer is precisely equivalent to the full form New City{…}.