Chapter
4
Introduction to Visual Basic .NET
Many Visual FoxPro developers have an aversion to anything that
bears the name “Visual Basic”. This chapter aims to help you look past this
prejudice and take a fresh look at the new incarnation of Visual Basic—Visual
Basic .NET. As you read this side-by-side comparison of Visual FoxPro and
Visual Basic .NET, you’ll see that Visual Basic has grown up and is a
first-class citizen alongside C# and C++.
Visual Basic has been around for many years. It was the
first language offered by Microsoft that brought Windows programming to the
masses. The relationship between Visual FoxPro and Visual Basic communities has
often been combative and characterized by religious fervor on both sides of the
fence.
One of the biggest bones of contention has been the claim by
VB developers that Visual Basic 6 is object-oriented—which most VFP developers
argue loudly against! But things have changed. For all intents and purposes,
Visual Basic .NET is a new language. Its syntax is similar to Visual Basic, but
it was completely rewritten for .NET.
In the next chapter, I’ll cover detailed information on both
C# and VB .NET’s object-oriented features. In this chapter, I focus on the
syntax of VB .NET compared to VFP. So, hopefully you can put aside any
preconceived notions and take a good look at what VB .NET has to offer.
For a side-by-side comparison of Visual Basic .NET, C#, and
Visual FoxPro’s operators and keywords, check out “Appendix A – Language Comparison
Tables”. For a comparison of each language’s data types, see “Appendix B – Data
Type Comparison”.
Changes for Visual Basic 6 backward compatibility
As you learn Visual Basic .NET, you’ll come across a
few things that are a little different from the .NET norm. After Visual Studio
.NET Beta 1 was released, Microsoft
restored some Visual Basic 6 functionality to VB .NET based on feedback from
the Visual Basic community. The changes provide an easier upgrade path from
Visual Basic 6 to Visual Basic .NET. These are the three main changes:
·
The value of True – In almost every
programming language, when a boolean True is coerced to an integer, its value
is one (1). In Visual Basic, it’s always been a minus 1 (-1). Originally,
Microsoft was going to change this so VB .NET was in line with other .NET
languages, but for backward compatibility reasons VB .NET’s True still
evaluates to -1.
·
Behavior of And/Or/Not/XOr – Originally,
Microsoft intended to change the And, Or, Not, and XOr operators from bitwise
operators (as they were in Visual Basic 6) to logical operators. Based on
feedback from the VB community, they left these as bitwise operators and added
two new operators instead: AndAlso and OrElse.
·
Declaring Arrays – To bring VB .NET in
line with other .NET languages, Microsoft intended to change the way arrays are
declared from how it was done in Visual Basic 6. Again, to maintain backward
compatibility, they changed it back to the Visual Basic 6 model. Check out the
“Arrays” section later in this chapter
for details.
Weak Typing vs. Strong Typing
While VB .NET is a strongly typed language, C# is a more strongly typed language. The
difference is in C# you must declare all variables and their types before using
them. In VB .NET, this is optional.
Option Explicit and Option Strict
VB .NET has two settings that specify how the compiler
treats variables—Option Explicit and Option Strict.
The Option Explicit setting specifies whether you can use
undeclared variables—not just undeclared variable types, but the variable
itself. By default, the Option Explicit setting is “Off”,
which allows you to use variables without declaring them. When Option Explicit
is “On”, VB .NET acts like C# by forcing you to declare all variables before
using them.
Although having the flexibility of being able to turn off
variable declaration checking may seem like a “plus”, it’s actually not. You
should always turn Option Explicit “On” so the compiler will catch the use of
undeclared variables. If Option Explicit is “Off”, the compiler won’t catch
variable names with typos resulting in unpredictable behavior at runtime.
Even when Option Strict is “On”, Visual Basic .NET differs a
bit from C# when it comes to using variables. In C#, you must initialize a
variable’s value before using it. In Visual Basic .NET, you can use a variable
without first setting its value (VB .NET sets all variables to a default value
when you declare them). Depending on whether you’re an advocate of compiler
enforcement or of flexibility you can argue whether this is a good or a bad
thing!
The Option Strict setting specifies whether the compiler
enforces strict typing. If Option Strict is “Off” (the default), the compiler
does not require you to specify a type when you declare a variable. If Option Strict
is “On”, then VB .NET acts like C#, forcing you to declare the type of all
variables. Option Strict also specifies how much checking the compiler performs
when converting between different variable types. If Option Strict is “Off”, no
type conversion checking is performed. If Option Strict is “On”, the compiler
warns you of any type conversions that may result in a loss of data. For
example, if Option Strict is “On” when you copy the value of a Long variable
into an Integer variable, the compiler complains because a Long variable can
hold values larger than can fit in an Integer. However, if you do the opposite
(copy the value of an Integer variable into a Long), the compiler does not
complain.
In general, it’s best to set Option Strict “On”. This allows
the compiler to catch any conversions that may result in a loss of data, rather
than trying to catch them at run time. In addition, explicitly specifying type
conversions has speed advantages over allowing them to occur implicitly
(automatically). This is because implicit conversions require extra work at
runtime to determine the types involved in a conversion.
Assuming that Option Strict and Option Explicit are both
“On”, you declare variables by specifying their name followed by their type.
For example, the following code declares a data variable named MyDate, a string
variable named MyString, and an integer variable named MyInteger:
Dim MyDate As DateTime
Dim MyString As String
Dim MyInteger As Integer
You specify the setting of Option Explicit and Option Strict
at the application level by means of VS .NET’s Solution Explorer. Just
right-click on a project, select Properties
from the shortcut menu, and select the Build
node under Common Properties
in the tree view (Figure 1). You can then set Option
Explicit and Option
Strict and it will affect all code in your project.
Figure 1. Typically, you should set Option
Explicit and Option Strict “On”, so the compiler catches undeclared variables,
variable types, and type conversion errors.
It is possible to override these project-level settings by
declaring a different setting for Option Explicit or Option Strict at the top
of your source files. For example:
Option Explicit Off
Public Class MyForm
Inherits
System.Windows.Forms.Form
End Class
Based on the “best practice” of using strong typing and
explicit variable declaration, the rest of the Visual Basic .NET sample code in
this book assumes that both of these options are set to “On”.
A simple Visual Basic .NET program
Although this chapter is not about Visual Basic .NET’s
object-oriented features, it’s difficult to learn the language syntax without
first learning how to create a simple program. Here is a “Hello .NET World”
program in VB .NET:
Module MyFirstVBNetProgram
Sub Main()
Console.WriteLine("Hello .NET World")
End Sub
End Module
There are a few things to note about this program. First of
all, every VB .NET program must have a procedure named Main, which is called when the program is
first executed. It must return nothing or an integer. If you want to return an
integer, you must specify that Main
is a Function
Procedure instead of a Sub Procedure:
Module MyFirstVBNetProgram
Function Main() As Integer
Console.WriteLine("Hello .NET World")
Return 0
End Function
End Module
You can also specify that Main accept a string array parameter. If
any command-line parameters are passed when the program is executed, they are
placed into this array:
Module MyFirstVBNetProgram
Function Main(ByVal CmdArgs() As String) As Integer
Console.WriteLine("Hello .NET
World")
' Process any parameters
If CmdArgs.Length > 0 Then
' Build a string containing all parameters
Dim Parms, Parameter As String
For Each Parameter In CmdArgs
Parms += Parameter & " "
Next
' Display the parameters
Console.WriteLine(Parms)
End If
Return 0
End Function
End Module
Notice the use of the += operator. In Visual Basic .NET this
is a shortcut for:
Parms = Parms + Parameter
Although it’s technically accurate for a VB .NET program to have
a procedure named Main, in practice, you may
not see such a method anywhere in your source code. For example, if you create
a new Visual Basic .NET Windows Application using Visual Studio .NET, you won’t
find a Main method. What’s happening is behind the scenes the compiler injects
a Main method into the IL for you. You can override this behavior and manually
create your own Main method.
Visual Basic .NET Syntax
This section provides an overview of VB .NET’s language
syntax compared to Visual FoxPro.
Case insensitivity
Visual Basic .NET is like Visual FoxPro in that it is
case insensitive. Although the convention in VB .NET is to proper case
keywords, you can make them upper case, lower case, or anything in between and
the compiler treats them all the same. In C#, keywords are in lower case. If
you use upper case or mixed case, the compiler flags it as an error.
To demonstrate case insensitivity, in the following code I
have declared a variable, “MyString”, and assigned it a value. In the next
line, I reference that variable, but I refer to it as “mystring” (all
lowercase). In VB .NET and Visual FoxPro, these two names refer to the same
variable:
Dim MyString As String = "Visual Basic .NET is
case-insensitive"
Console.WriteLine(mystring)
In contrast, as mentioned in Chapter 3, “Introduction to C#”,
C# is case sensitive. If you are the type of developer who tends to mix
case freely, this can be a real factor when choosing between Visual Basic .NET
and C#. If you tend to be stricter with your casing (and you let IntelliSense
“fill in the blanks” for you), it’s not as big of an issue.
End-of-line and line continuation characters
In the area of end-of-line and line continuation
characters, Visual Basic .NET is again similar to Visual FoxPro. In VB .NET, a
CR+LF indicates the end of a line. If you need to have a statement span
multiple lines, you must use the continuation character. In Visual FoxPro, the
continuation character is the semicolon (;), but in Visual Basic .NET, it is
the underscore
( _ ) character.
Grouping statements together
Visual Basic .NET groups statements together by
matching beginning and ending keywords. For example, a class definition begins
with the Class
keyword and ends with End Class.
A subroutine starts with the keyword Sub and ends with End
Sub:
Class MyClass
Public Sub MySubroutine()
End Sub
End Class
The use of starting and ending
keywords is similar to Visual FoxPro:
DEFINE CLASS MyClass
AS Session
PROCEDURE MyProcedure
ENDPROC
FUNCTION MyFunction
ENDFUNC
ENDDEFINE
Comments
In VB .NET, you use a single quote character to
indicate the start of a comment. This is consistent whether the comment is at the
beginning of a line or following a statement:
' Here is a comment at the beginning of a line
Dim MyInteger As Integer = 100 ' Here is a comment following a statement
Since statements cannot automatically span lines in Visual
Basic .NET without a continuation character, there is no multi-line comment
indicators available as in C#.
Namespaces
In Visual Basic .NET, you use the imports
keyword to specify where the compiler should look to find classes that are not
declared in the current namespace. For example:
Imports System.Data.OleDb
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
All Visual Basic .NET projects automatically import several
default namespaces. Since these are imported globally at the project level, you
do not need to import these namespaces elsewhere in your project. Different
types of projects automatically import different namespaces. To see the default
namespaces imported into your project, right-click on your project in the
Solution Explorer and select Properties
from the shortcut menu. Select the Imports
node located under the Common
Properties node and you will see a list of default namespaces in
the Project Imports
list box (Figure 2). Visual Studio .NET allows you to add and remove
namespaces from this list.
Figure 2. Visual Basic .NET automatically adds
several default namespaces to each project you create. If a namespace appears
in this list, you do not need to explicitly declare that you are using the
namespace elsewhere.
Visual Basic .NET has another interesting namespace feature—a
project root namespace. To see your project’s root namespace,
right-click on your project in the Solution Explorer and select Properties from the
shortcut menu. Select the General
node located under the Common
Properties node and you will see your project’s root namespace (Figure
3).
Figure 3. You can specify a root namespace for
your project in your project’s Properties dialog.
By default, all classes in your project belong to this root
namespace. The root namespace acts as a prefix for all other namespaces
declared in the project. For example, if a project’s root namespace is
“HW.NetBook”, declaring the “Business” namespace in the following code sample
associates the Employee class with the HW.NetBook.Business namespace.
Namespace Business
Public Class Employee
End Class
End Namespace
Defining a simple class
Although I am reserving most of the information about
object-orientation in Visual Basic .NET for the next chapter, it’s easier to
understand VB .NET’s syntax in the context of a class definition. Here is the
simplest class definition in VB .NET:
Class MyFirstVBClass
End Class
Below is the simple class with a single, simple method.
Notice I’ve associated the class with the namespace Samples. If the project’s root
namespace is HW.NetBook (as it is in this book’s sample code), the fully
qualified namespace of this class is HW.NetBook.Samples.
Namespace Samples
Public Class MyFirstVBClass
Public
Sub SayHello()
MessageBox.Show("Hello
.NET World!", "Visual Basic .NET")
End
Sub
End Class
End Namespace
Unlike the equivalent C# sample code in the previous chapter,
you do not need to explicitly import the System.Windows.Forms namespace to use
the MessageBox class because, by default, this namespace is imported at the
project level.
The default base class
If you do not specify a parent (base) class, it is
assumed that a class is derived from the
Object class. As mentioned previously, the Object class is the topmost class in
the .NET Framework hierarchy.
Defining class methods
Visual Basic .NET has two different types of
methods—subroutines and functions. If your method does not return a value, you
must declare it as a subroutine. If it does return a value, you must
declare it as a function.
Here is the subroutine declaration syntax:
[Attributes][ProcedureModifier] Sub Identifier [([ FormalParameterList
])]
' Method body
End Sub
Here is the function declaration syntax:
[Attributes][ProcedureModifier] Function Identifier [([ FormalParameterList
])]
[ As [Attributes] TypeName]
' Method body
End Function
Notice that functions have an additional As
clause that specifies the return value and its type. As discussed in the
“Option Strict and Option Explicit” sections earlier in this chapter, if Option
Strict is “On”, you must specify the types of parameters and return values. If
it is “Off” and no return type is specified for the function, an Object type is
automatically returned.
Returning values from a method
There are two different ways to return a value from a
function. You can use the Return statement (which is new in Visual Basic
.NET):
Public Function ReturnValue1() As Integer
Dim intReturnValue As Integer = 1
Return intReturnValue
End Function
You can also return a value from a method by setting the name
of the function to the value to be returned:
Public Function ReturnValue2() As Integer
Dim intReturnValue As
Integer = 2
ReturnValue2 =
intReturnValue
End Function
I recommend using the Return statement
to return a value from a Visual Basic .NET method, because it is far more
intuitive than setting the name of the function to the value being returned.
This makes it easier for others who are perusing your code to figure out what’s
going on.
Details regarding the syntax of method declarations are
discussed further in Chapter 5, “Object Orientation in C# and Visual Basic
.NET”.
Declaring variables
Variables declared within methods are known as local
variables (there are no other kind).
They are only visible within the method where they are declared. This is
different from
Visual FoxPro, which allows you to declare variables within a method that are
local, private, or global.
Having only local variables
at your disposal in both Visual Basic .NET and C# is not restrictive. Good
programming practice dictates that you should always declare method variables
as local. In Visual FoxPro, rather than using private “mystery” variables, if
you want a sub method to see a variable, you should pass it explicitly as a
parameter.
To declare a local variable, use the Dim
statement followed by the variable name, the As keyword, and
the type of the variable:
Dim Count As Integer ' Declare an integer variable named
Count
Count = 5
' Assign Count the value of 5
You can also declare a variable and assign it a value in a
single command:
Dim Height As Integer = 6 ' Declare an int variable and
assign it a value of 6
If you want to declare multiple variables of the same type in
a single statement, simply separate them with commas:
Dim Top, Left As Integer
When you declare multiple values in a single line, you can’t
specify default values as you can in C#. However, Visual Basic .NET does allow
you to do something you can’t in C#—declare multiple variables of different
types in a single line.
Dim Bottom As Integer, FieldName As String
Member variables
As mentioned previously, variables declared at the
method level are known as local
variables. However, variables declared at the class level are known as member
variables or instance variables:
Public Class MemberAndLocalVariables
Private Test1 As String =
"Test1" ' Declare a member variable
Public Sub
DeclareVariables()
Dim Test2 As String =
"Test2" ' Declare a local
variable
MessageBox.Show("Displaying
" & Test1, 'Member Variable')
MessageBox.Show("Displaying
" & Test2, 'Local Variable')
End Sub
End Class
At first, it may seem that member variables are the same as
Visual FoxPro properties, but they’re not. In addition to member variables, VB
.NET classes can also have properties, which are discussed in Chapter 5,
“Object-Orientation in C# and Visual Basic .NET”. For now, just think of member
variables as variables declared at the class level that are accessible to all
methods in the class.
One other point to note is you can reference member variables
the same way you reference local variables. You don’t need a qualifier such as
“this” as you do in Visual FoxPro. In the previous example, you could have
referenced the Test1 field as “Me.Test1”. The keyword Me
in Visual Basic .NET is equivalent to “This” in Visual FoxPro.
Member variable modifiers
There are five different accessibility modifiers you
can apply to member variables (Table 1).
Table 1. Field modifiers allow you to specify the
visibility of your fields
Modifier
|
Description
|
public
|
Access is not restricted
|
friend
|
Access is limited to the
current project
|
protected
|
Access is limited to the containing class or subclasses
|
protected friend
|
Access is limited to the current project or to subclasses
|
private
|
Access is limited to the containing class
|
It’s usually best to specify that a member variable is
private. To promote this practice, if you don’t declare an accessibility modifier,
Visual Basic .NET considers it private by default. If you want other classes to
have access to this field, rather than changing the accessibility modifier, you
should create a protected or public property (for details, see the “Properties”
section in Chapter 5, “Object-Orientation in C# and Visual Basic .NET”).
Value and reference types
In Chapter 3, “Introduction to C#”, the “Value and
reference types” section discussed the difference between value and reference types
in the .NET Framework. The distinction between these two different types is the
same for all .NET languages—including Visual Basic .NET. Refer to this section
in chapter 3 for more details.
The string type
Although the commands used to manipulate a string make
it seem like a value type, a string is actually a reference type.
You assign a value to a string variable using a string
literal enclosed in double quotes:
Dim Caption As String = ".NET for VFP
Developers"
Unlike Visual FoxPro, you can’t use a single quote or square
brackets to delimit strings (the single quote is reserved for comments in VB
.NET). You concatenate strings in Visual Basic .NET by using either an
ampersand (&) or a plus (+) sign (as in VFP):
MessageBox.Show(str1 & " " & str2,
"Concatenate with &")
MessageBox.Show(str1 + " " + str2,
"Concatenate with +")
Again, the next logical question is, “How do I create a
string literal that contains double quotes such as Louis “Satchmo” Armstrong”?
You can do this easily by using two double quote marks consecutively:
Dim ManlyMen As String = "Louis
""Satchmo"" Armstrong"
Visual Basic .NET does not recognize any other special
character escapes within a string (such as “\n” for a new line in C#). For
details, see the “The string type” section in Chapter 3, “Introduction to C#”.
Rather than using character escapes, VB .NET provides
enumerated values instead (Table 2). For details, see the “Enumerations”
section later in this chapter.
Table 2. VB .NET has enumerated
values you can concatenate to your strings. This table contains a partial list.
Enumeration
|
Description
|
CrLf
|
Carriage return / linefeed
|
Cr
|
Carriage return
|
Lf
|
Line feed
|
NewLine
|
New line character (same as carriage return / line feed)
|
Tab
|
Tab
|
FormFeed
|
Form feed
|
If you import the Microsoft.VisualBasic.ControlChars
namespace, you can simply use the values specified in the “Enumeration” column
of Table 2. For example:
MessageBox.Show("Line 1" + NewLine + "Line
2", "New Line Demo")
Strings as reference types
.NET runtime treats strings a bit differently than
other reference types. From a practical perspective, this only becomes an issue
when you are concatenating a number of strings together (such as in a loop),
because the runtime can proliferate an excess amount of string data on the
heap. In situations such as this, you should use the .NET StringBuilder class
instead of using Strings.
The StringBuilder class has an Append method you use to
concatenate strings together:
Dim StrBuilder As New StringBuilder()
StrBuilder.Append("Texas,
")
StrBuilder.Append("New Mexico, ")
StrBuilder.Append("Colorado")
MessageBox.Show(StrBuilder.ToString(), "StringBuilder")
Enumerations
Visual Basic .NET allows you to define your own complex
value types. One of these value types is enumerations and the other is
structures (covered in Chapter 5, “Object Orientation in C# and VB .NET”).
Enumerations are a convenience feature of Visual Basic .NET
that allows you to group related constants together. For more information on
the beauty of enumerations, check out “Enumerations” in Chapter 3,
“Introduction to C#”.
Here is an example of declaring an enumeration in Visual
Basic .NET:
Public Enum Months As Integer
January = 1
February = 2
March = 3
April = 4
May = 5
June = 6
July = 7
August = 8
September = 9
October = 10
November = 11
December = 12
End Enum
You access an enumeration by referencing its name and
specifying the desired member. The compiler converts it to its associated
integer value:
Public Class EnumerationTest
Public Function
GetBookPubMonth() As Integer
' Access the
enumeration
Dim PubMonth As
Months = Months.September
Return PubMonth
End Function
End Class
Although an incrementing integer is the most common form of
an enumeration, your enumeration constant values can be any integer value,
including negative numbers, and in any order. For example, the following
enumeration lists three people’s last names in alphabetical order, causing
their windsurfing ability rating to appear in non-sequential order:
Public Enum WindSurfingAbility As Integer
Egger = 9
Fabulous_Ferguson = 8
McNeish = -3
Strahl = 10
End Enum
Although enumerations are Integer types by default, you can
specify that they are Byte, Integer, Long, or Short. For example:
Public Enum HairLength As Long
As Long specifies that the HairLength class is
derived from the type “Long”. For details on subclassing and inheritance, see
Chapter 5, “Object Orientation in C# and Visual Basic .NET.
Arrays
All arrays in VB .NET are zero-based, meaning the first
element of the array is zero (0), rather than one (1) as in Visual FoxPro. In
addition, all arrays must contain values of the same type. You can’t mix and
match integers, strings, dates, and so on in a single array.
Declaring Arrays
In Visual Basic .NET, arrays are declared the same way
as other variables, except you add parentheses after the array name:
Dim KidsAges() As Integer
You can also declare an array and size it in one step:
Dim KidsNames(2) As String
If you compare this line of VB .NET code to the same C# code,
you’ll notice a difference in the declared size of the array. In C#, I would
set the size of the array to three (3) elements. Here, it looks like I’ve sized
the array to only contain only two—however, this is not the case. In order to
maintain backward compatibility with Visual Basic 6, the way you declare arrays
in Visual Basic .NET is slightly different from other .NET languages.
When you declare the size of an array in VB .NET, you declare
the upper limit of the array rather than the total number of elements. For
example, in the KidsNames array declared here, I want a total number of three
elements. Since arrays are zero-based, the first element is zero, the second
element is one, and the last element is two. In VB .NET, I use this upper
element value to specify the size of the array.
Although this is non-standard, this concession was made by Microsoft’s
VB .NET engineers to allow backward compatibility with Visual Basic 6.
Redimensioning arrays
Unlike C#, you can change the size of any array
dimension by using VB .NET’s ReDim statement. The following code shows how to
dimension and redimension an array:
Dim ScaryAnimals() As String = {"Lions",
"Tigers"}
ReDim Preserve ScaryAnimals(2)
The first line of this code dimensions the array size to two
implicitly, since I have specified two string elements (Lions and Tigers). The
second line redimensions the array to hold three elements (remember, VB .NET’s
idiosyncrasy—you specify the highest element number rather than the total
number of elements). Notice the use of the keyword Preserve. If you
do not add this keyword, VB .NET clears out the other array elements when it
redimensions the array. Note that ReDim can only be
used on an existing array—you can’t initialize a new array by using ReDim.
Also, you can only change the size of an array dimension using ReDim;
you can’t change the number of dimensions.
Storing values to arrays
You set initial values of array elements when you
declare an array:
Dim KidsMiddleNames() As String =
{"Christopher", "Mark", "James"}
Or, you can store values in the array
elements after declaring the array:
Dim KidsNames(2) As String
KidsNames(0) = "Jordan"
KidsNames(1) = "Timothy"
KidsNames(2) = "Alexander"
Sorting arrays
You easily sort the elements of an array by calling the
Array class’ Sort method:
Array.Sort(KidsNames)
You reverse the sort order by calling
the Array class’ Reverse method:
Array.Reverse(KidsNames)
Multidimensional arrays
In Visual FoxPro, you can create one and
two-dimensional arrays. Visual Basic .NET allows you to create multidimensional
arrays—arrays with three or more dimensions.
Multidimensional arrays are either rectangular (every row has
the same number of columns) or jagged (each row can have a different number of
columns).
Defining multidimensional rectangular arrays
In VB .NET, you declare a multidimensional, rectangular
array by adding one or more commas within the parentheses of the array
declaration. Each comma you add specifies an additional array dimension. Here
is the definition of a two-dimensional, rectangular array:
Dim ArrayKids(,) As String = {{"Jordan",
"McNeish"}, _
{"Timothy",
"McNeish"}, _
{"Alexander", "McNeish"}}
Defining jagged arrays
A jagged array is an “array of arrays”. They are also
multidimensional arrays, but each row can have a different number of columns. You
define a jagged array by adding an extra set of parentheses for each dimension.
In the following example, the jagged array has three elements in its first
dimension. Its second dimension has a different size for each row. The first
row has three columns, the second row has two columns, and the third row has
one column:
Dim Musicians()() As String = {New String()
{"Stevie", "Ray", "Vaughn"}, _
New String()
{"Jimi", "Hendrix"}, _
New String()
{"Bono"}}
' Show all three names of the first musician
MessageBox.Show(Musicians(0)(0) + " " & _
Musicians(0)(1) & " " & _
Musicians(0)(2), "Jagged Arrays")
Type conversions
When working with strongly typed languages, converting
between different data types is an important consideration. VB .NET provides
both implicit and explicit type conversion.
For a list of VB .NET data
types and a comparison between VB .NET, C#, and VFP data types, check out
“Appendix C – Data Type Comparison”.
Implicit type conversions
Visual Basic .NET implicitly converts some values from
one type to another. In the following example, VB .NET converts a short value
to an integer and then to a double:
Dim x As Short = 10
Dim y As Integer = x
Dim z As Double = y
Table 3 lists the types that Visual Basic .NET can
implicitly (automatically) convert.
Table 3. Types that Visual Basic .NET can
implicitly convert.
From Type
|
To Type
|
byte
|
ushort, short, uint, int,
ulong, long, float, double, decimal
|
sbyte
|
short, int, long, float,
double, decimal
|
short
|
int, long, float, double, decimal
|
ushort
|
uint, int, ulong, long, float, double, decimal
|
char
|
ushort, uint, int, ulong, long, float, double, decimal
|
int
|
long, float, double, decimal
|
uint
|
long, ulong, float, double, decimal
|
long
|
float, double, decimal
|
ulong
|
float, double, decimal
|
float
|
double
|
Explicit type conversion
If the compiler refuses to implicitly convert a value
from one type to another, you can explicitly convert it yourself. Visual Basic
.NET provides a number of ways to do this.
The first method is to use Visual Basic .NET’s conversion
keywords (Table 4).
Table 4. Visual Basic .NET provides conversions
keywords you can use to explicitly convert values from one type to another.
Keyword
|
Description
|
CBool
|
Converts any numeric type,
String, Object to Boolean
|
CByte
|
Converts any numeric type,
any enumerated type, Boolean, String, Object to Byte
|
CChar
|
Converts String, Object to Char
|
CDate
|
Converts String, Object to Date
|
CDbl
|
Converts Any numeric type, Boolean, String, Object to
Double
|
CDec
|
Converts any numeric type, Boolean, String, Object to
Decimal
|
CInt
|
Converts any numeric type, Boolean, String, Object to
Integer
|
CLng
|
Converts any numeric type, Boolean String, Object to Long
|
CObj
|
Converts any type to Object
|
CShort
|
Converts any numeric type, Boolean, String, Object to
Short
|
CSng
|
Converts any numeric type, Boolean, String, Object to
Single
|
CStr
|
Converts any numeric type, Boolean, Char, Char() array,
Date, Object to String
|
For example, to convert an Integer to Byte you use the CByte
keyword:
Dim x As Integer = 20
Dim y As Byte = CByte(x)
You can also use the System.Convert class to perform
conversions instead. The Convert class has a number of different conversion
methods to use for converting values (Table 5). For example, to perform
the same conversion in the previous example using the Convert class, you do it
this way:
Dim x As Integer = 20
Dim y As Byte = Convert.ToByte(x)
You will experience better performance using the System.Convert
class rather than the conversion functions. This is because the Convert class
has overloaded methods specifically designed to convert each different type.
However, the type conversion functions such as CStr and CDate take into
consideration the locale settings of your system, so if this functionality is
important to you, it may be worth the performance hit.
Table 5. The Convert class contains a number of
methods to use for converting values from one type to another. This is a
partial list.
Keyword
|
Description
|
ToBoolean
|
Converts a value to Boolean
|
ToByte
|
Converts a value to an 8-bit unsigned
integer
|
ToChar
|
Converts a value to a Unicode character
|
ToDateTime
|
Converts a value to DateTime
|
ToDecimal
|
Converts a value to Decimal
|
ToDouble
|
Converts a value to Double
|
ToInt16
|
Converts a value to a 16-bit signed Integer
|
ToInt32
|
Converts a value to a 32-bit signed Integer
|
ToInt64
|
Converts a value to a 64-bit signed integer
|
ToSByte
|
Converts a value to an 8-bit signed integer
|
ToSingle
|
Converts a value to a single-precision floating point
number
|
ToUInt16
|
Converts a value to a 16-bit unsigned integer
|
ToUInt32
|
Converts a value to a 32-bit unsigned integer
|
ToUInt64
|
Converts a value to a 64-bit unsigned integer
|
The CType function
The conversion keywords and System.Convert class
discussed in the previous section are great for converting basic value types,
but you need something else if you want to convert more complex objects. That
something else is the CType function.
CType is a Visual Basic .NET function that
allows you to convert an expression to a data type, an object, structure,
class, or interface. The CType function accepts two parameters. The
first parameter is an expression to be converted. Often this first parameter
contains an object reference. The second parameter is the destination type you
want the expression converted to. For example, the following code converts an
integer to decimal:
Dim x As Integer = 100
Dim y As Decimal = CType(x, Decimal)
Converting to string
If you need to convert a value to a string, the Object
class has a ToString method that is inherited by all classes in the .NET
Framework. This method returns the string representation of the object. So, for
example, do the following to get a string representation of an integer:
Dim i As Integer = 10
Dim s As String = i.ToString()
Converting strings with Val
If you need to convert strings to value types, you can
use one of the conversion keywords listed in the “Explicit type conversion”
section earlier in this chapter. In addition, you can use the Val
function, which is a little more forgiving when it comes to converting strings
to numeric values—it lets you convert strings that contain both numeric and
character values.
Val() stops converting a string when it hits a
character that it can’t recognize as part of a number. In the following
example, the string containing the value “567 Test” is converted by the Val()
function. The resulting value is 567:
Dim i As Double
Dim z As String = "567 Test"
i = Val(z) ' Returns
567
Boxing and unboxing in Visual Basic .NET
As described previously, boxing is the process of
converting a value type to a reference type. Unboxing is the process of
converting the value of a reference type back to a value type.
For example, Boxing occurs implicitly when you store an
integer into an object:
Dim x As Integer
Dim y As Object = x
For a diagram showing what happens in memory when a value is
boxed, check out “Boxing and unboxing values” in Chapter 3, “Introduction to C#”.
In Visual Basic .NET, you cannot explicitly unbox values the
same way as you can in C#.
Because Visual Basic .NET
cannot explicitly unbox values, it relies on the helper functions found in the
Microsoft.VisualBasic.Helpers namespace, which are far less efficient than C#’s
explicit unboxing.
The TypeOf operator
You can determine if an object is of a particular type
by using the TypeOf
operator. This is useful in situations where a method receives a generic Object
parameter and wants to determine its specific type. For example, the following
method receives a parameter of type Object. It then checks if it is of the type
MyClass1:
Public Class
TypeOfOperatorDemo
Public Sub CheckClass(ByVal TestObject As Object)
If TypeOf TestObject Is MyClass1 Then
MessageBox.Show("TestObject is MyClass1",
"TypeOf operator")
Else
MessageBox.Show("TestObject is not MyClass1",
"TypeOf operator")
End If
End Sub
End Class
If statement
Visual Basic .NET’s If statement is
similar to Visual FoxPro’s IF..ENDIF statement. If the expression being
evaluated is true, the code following Then is executed.
Optionally, you can add an Else statement to the If
that gets executed if the condition expression evaluates to False. You can also
nest If
statements.
Dim HavingFun As Boolean = True
If HavingFun Then
MessageBox.Show("We
are having fun!", "if demo")
Else
MessageBox.Show("We
are NOT having fun!", "if demo")
End If
If you want to test an additional condition in the Else,
use ElseIf:
Dim MyInteger As Integer = 99
If MyInteger < 10 Then
MessageBox.Show("MyInteger
is less than 10", "If...End If")
ElseIf MyInteger < 100 Then
MessageBox.Show("MyInteger
is more than 9, but less than 100", "If...End If")
End If
Select…Case
statement
The Visual Basic .NET Select…Case
statement is equivalent to Visual FoxPro’s
DO CASE statement. Based on the value of the expression, one of the case
statements is selected for execution. You can specify a Case
Else, which is the same as VFP’s OTHERWISE clause. If the switch
expression does not match any of the cases, control is passed to the Case
Else. If no Case Else is present, control passes to the
first command following the End Select.
Dim TestValue As Integer = 3
Select Case TestValue
Case 1
MessageBox.Show("TestValue
= 1", "Select...Case")
Case 2
MessageBox.Show("TestValue
= 2", "Select...Case")
Case 3, 4
MessageBox.Show("TestValue
= 3 or 4", "Select...Case")
Case Else
MessageBox.Show("TestValue
is not 1, 2, 3, or 4", "Select...Case")
End Select
Unlike C#, you don’t have to add a break
statement at the end of each case, which is a nice feature!
For…Next loop
Visual Basic .NET’s For…Next loops are
equivalent to Visual FoxPro’s FOR…ENDFOR command. It iterates through a loop
while a particular condition is true.
In the For…Next loop, the loop executes for as long
as the counter variable is between the specified values. The Next
statement is typically used to increment or decrement the counter value.
Dim i As Integer
Dim Message As String
For i = 0 To 3
Message += "Message
" + i.ToString() + NewLine
Next i
You exit out of a For…Next loop at
any point by using the Exit For statement.
While loop
The While loop is equivalent to Visual FoxPro’s
DO…WHILE loop. It is a pre-test loop meaning that if the condition evaluates to
false, the loop is not executed at all. While loops are
often used to repeat a block of code for an undetermined number of times.
Public Sub WhileLoopDemo()
Dim Condition As
Boolean = True
While Condition
Dim i As Integer = 1
MessageBox.Show("While loop count " + i.ToString(), _
"While
loop")
i += 1
Condition = False
End While
End Sub
You exit out of a While loop at any
point by using the Exit While statement.
Do loop
The Visual Basic .NET Do loop repeats a
block of statements while a condition is true or until a condition becomes
true. If you use the Do While construct, the loop executes while a
condition is true. If you use the Do Until
construct, the loop executes until the condition becomes true.
The While and Until keywords can
be used at either the top or bottom of the loop. If they are used at the top of
the loop, the condition is checked before the loop is executed. If they are
placed at the bottom of the loop as shown in the following example, the
condition is checked after the loop executes. This means the loop always
executes at least once. This is different than Visual FoxPro’s DO WHILE loop,
which only evaluates the condition at the top of the loop.
Dim Condition As Boolean = False
Do
Dim i As Integer = 1
MessageBox.Show("Do
While loop count " + i.ToString(), _
"Do...While loop")
i += 1
Loop While Condition
You exit out of a Do loop at any
point by using the Exit Do statement.
For Each loop
The Visual Basic .NET For Each loop
executes a group of statements for each element in an array or item in a
collection. It is equivalent to Visual FoxPro’s FOR EACH command.
Dim VersionList, Version As String
Dim VSNetVersions() As String = {"Standard", "Professional",
_
"Enterprise Developer", _
"Enterprise Architect"}
For Each Version In VSNetVersions
VersionList += "VS
.NET " + Version + NewLine
Next
MessageBox.Show(VersionList, "ForEach loop")
You exit out of a For Each loop at
any point by using the Exit For statement.
With statement
Visual Basic .NET’s With statement is
equivalent to Visual FoxPro’s WITH…ENDWITH command. You specify an object
reference at the top of the With statement, then refer to properties and
methods of the object within the statement by specifying the name of the
object. Any expression starting with a period in the With
statement is evaluated as if it is prefixed by the object name. For example:
Dim ReturnDemo As New ReturnValuesDemo()
Dim ReturnValue As Integer
With ReturnDemo
ReturnValue =
.ReturnValue1()
ReturnValue =
.ReturnValue2()
End With
XML Documentation Tool
Although XML documentation was not built into Visual
Studio .NET for VB .NET, several months after the release of VS .NET, a
stand-alone tool was released by Microsoft that allows you to create XML
documentation for VB .NET projects. To get this tool, download it from the VB
.NET “GotDotNet” Web site: http://www.gotdotnet.com/team/vb.
This tool works a bit differently than the Visual Studio .NET
XML documentation tool for C#. With C# XML documentation, you enter your XML
comments directly in your code. These comments are compiled into the assembly
and can be viewed in an Object Browser and with IntelliSense. In addition VS
.NET automatically builds XML Comment Web pages for you from these XML comments
(see Chapter 3, “Introduction to C#” for details).
With the VB .NET XML Documentation Tool, your XML comments
are not stored in the source code, but in a separate XML file. Like C#, these
XML comments can also be viewed in an Object Browser and with IntelliSense.
However, there is no facility to create Comment Web pages from these VB .NET
XML comments. In addition, since the comments are not stored in the source code
this means that:
1. Either,
you don’t put any comments in your source code (not recommended).
2. Or,
you duplicate your comments—one copy in your source code and one in the XML
file.
I see this as a serious limitation of this tool. You really should
place comments in your source code for your benefit and the benefit of
developers who have to examine your code.
After downloading the VB .NET XML Documentation Tool, you run
it by double-clicking the “XML Documentation Tool.exe” file. This launches the
XML Documentation Tool dialog (Figure 4).
Figure 4. The XML Documentation Tool for Visual
Basic .NET allows you to create XML comments for developers who do not have
access to your source code.
Check out the associated ReadMe.htm file for information on
how to use this tool to create XML comments for your VB .NET code.
Conclusion
Visual Basic .NET has come a long way from Visual Basic
6 and is now a powerful, fully object-oriented language. It’s as different as
FoxPro 2.6 and Visual FoxPro (and then some). Of all the .NET languages, its
syntax is most similar to Visual FoxPro and, as you would expect from Visual
Basic, there are a number of convenience features that make it worth looking at
as your programming language of choice. Since Microsoft has always stressed
Visual Basic’s ease of use, you can expect this emphasis to translate into even
more convenience features in the future.