Brief introduction
Visual Basic is always centered on generating practical, data-oriented line-of-business applications. Although migrating to. NET brings a unified framework and managed platform for application developers, the next version of Visual Basic includes a set of features that have a far-reaching impact on the productivity of developers who build data-oriented applications. These language extensions introduce common query tools that apply to all data sources, whether they are relational object graphs, hierarchical object graphs, or XML documents.
This document will briefly describe these new features.
Getting Started with Visual Basic 9.0
To see the real effects of these language features, let's first look at a real example-the CIA World Factbook database. The database contains a variety of geographical, economic, social and political information about the countries of the world. To demonstrate the example, we start with the name of each country/region, its capital/capital, total area, and the schema of the total population. This schema is represented in Visual Basic 9.0 by using the following classes (pseudocode for simplicity):
Class Country
Public Property Name As String
Public Property Area As Long
Public Property Population As Integer
End Class
The following is a small subset of the country/region databases that will be used to run the sample:
Dim countries = {
New Country With { .Name = "Palau", .Area = 458, .Population = 16952 }, _
New Country With { .Name = "Monaco", .Area = 1.9, .Population = 31719 }, _
New Country With { .Name = "Belize", .Area = 22960, .Population = 219296 }, _
New Country With { .Name = "Madagascar", .Area = 587040, .Population =
13670507}}
With this list, you can use the following query expression to query all countries/regions whose population is less than 1 million:
Dim smallCountries = From country In countries _
Where country.Population < 1000000 _
Select country
For Each country In SmallCountries
Console.WriteLine(country.Name)
Next
Since only Madagascar has a population of more than 1 million, the above procedures will print out the following country/region names after compiling and running:
Palau
Monaco
Belize
Let's examine the program to see the Visual Basic 9.0 features that make this program so simple. First, the declaration of each expression that represents Countries uses the new object initializer syntax new Country with {... Area = 458, ...} to create a complex object instance from a concise syntax that is similar to the With statement now, based on an expression.
The declaration also describes an "implicitly typed local variable" declaration in which the compiler infers the type of the local variable Countries by declaring an initializer expression to the right. The above declaration is exactly equivalent to an explicit type local variable declaration of the Country () type.
Dim countries As Country() = {...}
Again, this is still a strongly typed declaration; The compiler has automatically inferred the type on the right side of the local declaration, and the programmer does not have to enter the type manually in the program.
Initializes a local variable declaration using a SQL-style query expression smallcountries, filtering out all countries/regions with fewer than 1 million inhabitants. Query expressions are intended to resemble SQL, so programmers who already know SQL can learn more about Visual Basic query syntax faster.
Dim smallCountries = From country In Countries _
Where country.Population < 1000000 _
Select country
Note that this code example represents another implicitly-typed application: The compiler infers the type of smallcountries to IEnumerable (of Country) based on the result type of the query expression. The compiler converts the query expression itself into a call to the LINQ-enabled API, which implements the query operator for all types that implement IEnumerable (of T). In this case, the conversion is as simple as the following:
Dim smallCountries As IEnumerable(Of Country) = _
Countries.Where(Function(country) country.Population < 1000000). _
Select(Function(country) country)
The extended syntax depends on the lambda expression, which represents the inline function that returns the result of an expression. A lambda expression is converted to a delegate and passed to the extension function where, which is defined as an extension of the IEnumerable (of T) interface in the standard query operator library.
We've learned a few new things about Visual Basic 9.0, so let's take a closer look.
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 side of the 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 With { .Name = "Palau", ...}
Therefore, they are exactly equivalent to the following explicit type declarations:
Dim population As Integer = 31719
Dim name As String = "Belize"
Dim area As Float = 1.9
Dim country As Country = New Country With { .Name = "Palau", ...}
Because the type of the local variable declaration is inferred by the new Option infer on (the default value for the project), access to such variables is always early bound regardless of the setting of option Strict. The programmer must explicitly specify late binding in Visual Basic 9.0 by explicitly declaring the variable as type Object, as follows:
Dim country As Object = New Country With { .Name = "Palau", ... }
Inferred types prevent accidental use of late binding and, more importantly, enable strong extensions for new data types such as XML, as shown below.
For ..... Next or for Each ... The loop control variable in the Next statement can also be an implicitly typed variable. When you specify a loop control variable (as shown in the for I = 0 to Smallcountries.count or for every country in smallcountries), the identifier defines a new implicit type local variable whose type is expressed by an initializer or set of Inference and acts on the entire loop. By applying this type inference, you can rewrite the loop that prints all the small countries/regions, as follows:
For Each country In smallCountries
Console.WriteLine(country.Name)
Next
The type of the country is inferred as the country, that is, the smallcountries element type.
Object and Array initializers
In Visual Basic, the WITH statement simplifies access to multiple members of an aggregate value without having to specify the target expression multiple times. Within the WITH statement block, a member access expression that begins with a period is evaluated, as if the target expression of the WITH statement preceded the period. For example, the following statement Initializes a new Country instance and then initializes its field to the desired value:
Dim palau As New Country()
With palau
.Name = "Palau"
.Area = 458
.Population = 16952
End With
The new object initializer in Visual Basic 9.0 is an expression-based with statement that is used to succinctly create complex object instances. Using an object initializer, you can capture the two statements above into a single (implicitly typed) local declaration, as follows:
Dim palau = New Country With { _
.Name = "Palau", _
.Area = 458, _
.Population = 16952 _
}
Object initialization of this style in an expression is important to the query. Typically, a query is similar to an object declaration that is initialized by a Select clause to the right of the equal sign. Because the Select clause returns an expression, you must be able to initialize an entire object with a single expression.
As we've seen, object initializers also make it easy to create collections for complex objects. You can initialize an array and infer an element type by using an array initializer expression. For example, suppose the declaration of a city as a class,
Class City
Public Property Name As String
Public Property Country As String
Public Property Longitude As Long
Public Property Latitude As Long
End Class
You can create an array of capitals/capitals for the example country/region, as follows:
Dim Capitals = { _
New City With { _
.Name = "Antanarivo", _
.Country = "Madagascar", _
.Longitude = 47.4, _
.Latitude = -18.6 }, _
New City With { _
.Name = "Belmopan", _
.Country = "Belize", _
.Longitude = -88.5, _
.Latitude = 17.1 }, _
New City With { _
.Name = "Monaco", _
.Country = "Monaco", _
.Longitude = 7.2, _
.Latitude = 43.7 }, _
New City With { _
.Country = "Palau",
.Name = "Koror", _
.Longitude = 135, _
.Latitude = 8 } _
}