Chapter 16. Visual Basic 2005 Fundamentals

One goal of this book is for you to pick up the language fundamentals of Visual Basic 2005 as you create applications. Thus, Chapter 1 starts right off with building applications and eschews the traditional introduction to programming elements such as If statements, While loops, and so forth.

That said, Visual Basic 2005 is a full programming language with its own complexities. This chapter is aimed at readers who would like to get the fundamentals under their belt before reading the rest of the book (feel free to read this chapter first), or readers who want to review the fundamentals after reading the book, as well as readers who want to dip in now and then, to check how certain things are done as they read the book.

While this book is aimed at VB6 programmers making the transition to .NET, this chapter does not assume prior experience with Visual Basic or any other programming language, though if you’ve never programmed at all you may find the pace a bit quick.

Types

Every object in Visual Basic 2005 has a type. Types come in two flavors:

  • Those that are built into the language (called fundamental or intrinsic types )

  • Types you create (classes, structs, and interfaces)

Visual Basic 2005 offers a number of intrinsic types , as shown in Table 16-1.

Table 16-1. The intrinsic types

Type

Size (in bytes)

.NET type

Description

Boolean

1

Boolean

true or false.

Byte

1

Byte

Unsigned (values 0-255).

Char

2

Char

Unicode characters.

Date

8

DateTime

Midnight 1/1/0001 through 11:59:59 12/31/9999.

Decimal

12

Decimal

Fixed-precision up to 28 digits and the position of the decimal point. This is typically used in financial calculations. Requires the suffix “m” or “M.”

Double

8

Double

Double-precision floating-point; holds the values from approximately +/−5.0 * 10−324 to approximate +/−1.8 * 10308 with 15–16 significant figures.

Integer

4

Int32

Integer values between -2,147,483,648 and 2,147,483,647.

Long

8

Int64

Integers ranging from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.

Short

2

Int16

Integer values -32,768 to 32,767

Single

4

Single

Floating-point number. Holds the values from approximately+/-1.5 * 10-45 to approximate +/-3.4 * 1038 with 7 significant figures.

String

 

String

A sequence of Unicode characters.

Each type has a name (e.g., Integer) and a size (e.g., 4 bytes) The size tells you how many bytes each object of this type occupies in memory. Programmers generally don’t like to waste memory if they can avoid it, but with the cost of memory these days, you can afford to be mildly profligate if doing so simplifies your program.

Each Visual Basic 2005 type corresponds to an underlying .NET type. Thus, what Visual Basic 2005 calls an Integer, .NET calls an Int32. This is interesting only if you care about sharing objects across languages, an important topic but one that is beyond the scope of this book. The description field of Table 16-1 tells you the minimum and maximum values you can hold in objects of each type.

Numeric Types

Most of the intrinsic types are used for working with numeric values (Byte, Short, Integer, Single, Double, Decimal, Long).

Another way to divide the types is into those used for integer (whole number) values, and those used for fractional values. The Short, Integer, and Long types all hold whole number values. Most of the time, you’ll just use Integer for these values, unless there is a good reason to do otherwise.

The Single and Double types hold fractional values (rational numbers). For most uses, Single will suffice, unless you need to hold a really big fractional number, in which case you might use a Double. The Decimal value type was added to the language to support accounting applications, and is described in Table 16-1.

Nonnumeric types

In addition to the numeric types, the Visual Basic 2005 language offers four other primitive types: Char, String, Date, and Boolean .

The Char type is used from time to time when you need to hold a single character. For sequences of characters you’ll use the String type. Date types are used to hold date and time values, and are most useful when working with databases from which you might extract a date-time value.

The one remaining type of importance is Boolean. A Boolean value is a value that is either True or False.

Tip

The Boolean type was named after George Boole (1815-1864), an English mathematician who published “An investigation into the Laws of Thought, on Which Are Founded the Mathematical Theories of Logic and Probabilities,” and thus created the science of Boolean algebra.

Understanding types

When you create a program under Visual Basic 2005, you may choose to set Option Explicit and Option Strict to On, by writing these lines at the top of your source code:

Option Strict On
Option Explicit On

Tip

If you use Option Explicit or Option Strict, you must make them the first statements in your source code file.

Option Explicit requires that every variable be declared before it is used (variables are explained in the next section). Option Strict restricts the way you cast from one type to another. Both enable the compiler to help you find bugs in your program and together they make Visual Basic 2005 a strongly typed language; and that is a very good thing. This book assumes you will always set both Option Explicit and Option Strict on.

In a strongly typed language, every object you create or use must have a specific type (e.g., you must declare the object to be an Integer, a String, or a Dog). The type tells the compiler how big the object is and what it can do.

Tip

Confusingly, a perfectly legitimate type is type Object, though this type is rarely used and tends to undermine type safety.

The size of an object is measured in bytes. An Integer, for example, is four bytes big. User-defined types have a size as well, measured as the sum of all their member variables.

When programmers talk about what an object can do, they typically mean the methods of the object. User-defined types have many methods. Intrinsic types have implicit methods. For example, the numeric types have the ability to be added together, multiplied, and so forth.

The compiler will help you by complaining if you try to use a type improperly. The compiler complains in one of two ways: it issues a warning or it issues an error.

Tip

You are well advised to treat warnings as errors. That is, you ought to stop what you are doing and figure out why there is a warning and fix the problem. Never ignore a compiler warning.

Programmers talk about “design time,” “compile time,” and runtime.” Design time is when you are designing the program. Compile time is when you compile the program, and runtime is (surprise!) when you run the program.

The earlier you find a bug, the better. It is best (and cheapest) to discover a bug in your logic at design time. It is better (and cheaper) to find bugs in your program at compile time rather than at runtime. Not only is it better, it is more reliable. A compile-time bug will fail every time you run the compiler, but a runtime bug can hide. Runtime bugs slip under a crack in your code, and lurk there (sometimes for months) biding their time, waiting to come out when it will be embarrassing to you.

It is a constant theme of this book that you want the compiler to find bugs. The compiler is your friend. The more bugs the compiler finds, the fewer bugs your users will find. Setting Option Strict On helps the compiler find bugs in your code. Here’s how: suppose you tell the compiler that Milo is of type Dog. Some time later you try to use Milo to display text. Oops, Dog objects don’t display text. Your compiler will stop with an error.

Dog does not contain a definition for 'showText'

Very nice. Now you can go figure out if you used the wrong object or you called the wrong method.

Visual Studio 2005 actually finds the error even before the compiler does. When you try to add a method that does exist, IntelliSense pops up to help you, as shown in Figure 16-1.

When you try to add a method that does not exist, it won’t be in the list. That is a pretty good clue that you are not using the object properly.

IntelliSense
Figure 16-1. IntelliSense

Variables

A variable is an object that holds a value:

Dim myVariable as Integer = 15

In this example, myVariable is an object of type Integer. It has been initialized with the value 15. The formal definition for how you create a variable is:

               Access-Modifier Identifier As Type [= value]

Access modifiers are discussed later in this chapter; for now, you’ll use Dim.

Tip

The keyword Dim is short for dimension. This term dates back to the early days of BASIC programming, and is essentially vestigial.

An identifier is just a name for a variable, method, class, and so forth. In the case shown previously, the variable’s identifier is myVariable. The keyword As signals that what follows is the type, in this case Integer. If you are initializing the variable, you follow the type with the assignment operators (=) followed by the value (e.g., 15)

Type characters

Variable identifiers may have a type character suffix that indicates the variable’s type. For example, rather than writing as Integer you can use the suffix %.

Dim myVariable as Integer
Dim myVariable%

These two lines are identical in effect. Not every type is a character, but you are free to use them for those types that do. The complete set is shown in Table 16-2.

Table 16-2. Type characters

Type

Type character

Usage

Decimal

@

Dim decimalValue@ = 123.45

Double

#

Dim doubleValue# = 3.14159265358979

Integer

%

Dim integerValue% = 1

Long

&

Dim longValue& = 123456789

Single

!

Dim singleValue! = 3.1415

String

$

Dim stringValue$ = "Hello world"

Warning

While type characters were preserved in the Visual Basic .NET language, many developers feel they should be avoided, and that spelling out the type makes for clearer and easier-to-maintain code.

Initializing variables

You are not required to initialize variables. You could write:

Dim myVariable as Integer

You can then assign a value to myVariable later in your program:

Dim myVariable as Integer
'some other code here
myVariable = 15  'assign 15 to myVariable

You can also change the value of a variable later in the program. That is why they’re called variables, their values vary.

Dim myVariable as Integer
'some other code here
myVariable = 15  'assign 15 to myVariable
'some other code here
myVariable = 12  'now it is 12

Technically, a variable is a named storage location with a type. The value 12 is being stored in the named location. You can safely think of a variable as being an object of the type specified. You can assign values to that object and then you can extract those values later.

The use of variables is illustrated in Example 16-1. To test this program, open Visual Studio 2005 and create a Console application. Type in the code as shown.

Example 16-1. Initializing and assigning to variables
   Sub Main()
      Dim myInt As Integer = 7
      Console.WriteLine("Initialized myInt: {0}", myInt)
      myInt = 5
      Console.WriteLine("After assignment myInt: {0}", myInt)
   End Sub

Output:
Initialized myInt: 7
After assignment myInt: 5

Here, we initialize the variable myInt to the value 7, display that value, reassign the variable with the value 5, and display it again. To display the value we call the shared WriteLine method on the console class (see the sidebar "WriteLine“).

Default Values

Visual Basic 2005 does not require that you initialize your variables (though it is a very good idea to discipline yourself to do so). If you do not initialize your variable, it will be set to a default value, as shown in Table 16-3.

Table 16-3. Default values for uninitialized variables

Data type

Default value

All numeric types

0

Boolean

False

Date

01/01/0001 12:00:00 AM

Decimal

0

Object

Nothing

String

"" (zero length string)

Tip

Object defaults to Nothing. This keyword indicates that the variable is not associated with any object. You can assign the keyword Nothing to a reference to an object of any type.

Constants

Variables are a powerful tool, but there are times when you want to manipulate a defined value, one whose value you want to ensure remains constant. For example, you might need to work with the Fahrenheit freezing and boiling points of water in a program simulating a chemistry experiment. Your program will be clearer if you name the variables that store these values FreezingPoint and BoilingPoint, but you do not want to permit their values to be reassigned. How do you prevent reassignment? The answer is to use a constant. A constant is like a variable except that its value cannot be changed once it is initialized.

A constant associates a name with a value, but you cannot change that value while the program runs. Hence, rather than varying, a constant is, well, constant.

Constants come in three flavors: literals , symbolic constants , and enumerations.

Literal constants

A literal constant is just a value, such as 32. It does not have a name, it is just a literal value. And you can’t make the value 32 represent any other value. The value of 32 is always 32. You can’t assign a new value to 32; and you can’t make 32 represent the value 99 no matter how you might try.

When you write an integer as a literal constant, you are free just to write the number. The characters 32 are, together, a literal constant for the Integer value 32, and you can assign them accordingly:

Dim myValue as Integer = 32  'assign the literal value 32 to the variable myValue

If you want to assign a different type, however, you will want to use the correct format. For example, to designate the value 32 as a Double (rather than as an Integer) you will append the character R:

Dim myValue as Double = 32R 'assign literal value 32 as a Double

The complete list of literal formats is shown in Table 16-4.

Table 16-4. Literal formats

Type

Literal

Example

Boolean

True

False

Dim booleanValue as Boolean = True

Char

C

Dim charValue as Char = "J"C

Decimal

D

Dim decimalValue as Decimal = 3.1415D

Double

Any floating-point number, or R

Dim doubleValue as Double = 3.1415

Dim doubleValue as Double = 3.1415R

Dim doubleValue as Double = 5R

Integer

Any integer value in range, or I

Dim integerValue as Integer = 100

Dim integerValue as Integer = 100I

Long

Any integer value outside the range of type Integer, or L

Dim longValue as Long = 5000000000

Dim longValue as Long = 100L

Short

S

Dim shortValue as Short = 100S

Single

F

Dim singleValue as Single = 3.14F

String

" "

Dim stringValue as String = "Hello world"

Symbolic constants

Symbolic constants assign a name to a constant value. You declare a symbolic constant using the Const keyword and the following syntax:

                     access-modifierConst identifieras type = value;

Access modifiers are discussed later; for now, you will use Public.

The keyword Const is followed by an identifier (the name of the constant), the keyword As and the type of the constant (e.g., Integer). This is similar to declaring a variable, except that you add the keyword Const, and symbolic constants must be initialized. Once initialized, a symbolic constant cannot be altered. For example:

Public Const FreezingPoint As Integer = 32

In this declaration, 32 is a literal constant and FreezingPoint is a symbolic constant of type Integer. Example 16-2 illustrates the use of symbolic constants.

Example 16-2. Symbolic constants
   Sub Main()
      Const FreezingPoint As Integer = 32 ' degrees Farenheit
      Const BoilingPoint As Integer = 212

      Console.WriteLine("Freezing point of water: {0}", FreezingPoint)
      Console.WriteLine("Boiling point of water: {0}", BoilingPoint)
  
      'FreezingPoint = 0
   End Sub
End Module

Example 16-2 creates two symbolic integer constants: FreezingPoint and BoilingPoint. See the sidebar "Naming Conventions" for symbolic constants.

These constants serve the same purpose as always using the literal values 32 and 212 for the freezing and boiling points of water in expressions that require them, but because these constants have names, they convey far more meaning. Also, if you decide to switch this program to Celsius, you can reinitialize these constants at compile time, to 0 and 100, respectively; and all the rest of the code ought to continue to work.

To prove to yourself that the constant cannot be reassigned, try uncommenting the last line of the program (shown in bold). When you recompile, you should receive this error:

Constant cannot be the target of an assignment

Enumerations

Enumerations provide a powerful alternative to constants . An enumeration is a distinct value type, consisting of a set of named constants (called the enumerator list).

If you created two related constants:

Const FreezingPoint As Integer = 32
Const BoilingPoint As Integer = 212

you might wish to add a number of other useful constants as well, such as:

const LightJacketWeather As Integer = 60;
const SwimmingWeather As Integer = 72;
const WickedCold As Integer = 0;

This process is somewhat cumbersome, and there is no logical connection among these various constants. Visual Basic 2005 provides the enumeration to solve these problems:

Enum Temperatures
   CelsiusMeetsFahrenheit = −40
   WickedCold = 0
   FreezingPoint = 32
   LightJacketWeather = 60
   SwimmingWeather = 72
   BoilingPoint = 212
End Enum

Every enumeration has an underlying type, which can be any integral type (Byte, Short, Integer, and Long). The technical specification of an enumeration is:

[access modifiers] Enum 
                  identifier [As type]
      membername [ = constant expression]
 end Enum

Tip

In a specification statement like this, anything in square brackets is optional. That is, you can declare an Enum with no base type. The base type is optional, even if Strict is On, and if you don’t define a base type, integer is assumed.

For now, let’s focus on the rest of this declaration. An enumeration begins with the keyword Enum, which is followed by an identifier, such as:

Enum Temperatures

The AS keyword defines the underlying type for the enumeration. That is, are you declaring constant Integers, or constant Longs? If you leave out this optional keyword (and often you will) the underlying type will be integer.

Example 16-3 rewrites Example 16-2 to use an enumeration.

Example 16-3. Using an enumeration, not quite correctly
   Enum Temperatures
      WickedCold = 0
      FreezingPoint = 32
      LightJacketWeather = 60
      SwimmingWeather = 72
      BoilingPoint = 212
   End Enum 'Temperatures

   Sub Main()
      System.Console.WriteLine( _
         "Freezing point of water: {0}", _
         Temperatures.FreezingPoint)

      System.Console.WriteLine( _
           "Boiling point of water: {0}", _
           Temperatures.BoilingPoint)
   End Sub
End Module
Output:
Freezing point of water: FreezingPoint
Boiling point of water: BoilingPoint

In Example 16-3, you declare enumerated constant Temperatures. Temperatures is an enumeration. The values of the enumeration must be qualified by the enumeration type. That means you cannot just refer to FreezingPoint, but you must use the prefix Temperatures followed by the dot operator. This is called qualifying the identifier FreezingPoint. Thus, to refer to the FreezingPoint you use the full identifier Temperatures.FreezingPoint.

Unfortunately, if you pass the name of an enumeration to WriteLine what is displayed is its name, not its value. To display the value of an enumerated constant, you must cast the constant to its underlying type (Integer), as shown in Example 16-4.

Example 16-4. Casting the enumerated value to fix Example 16-3
   Sub Main()
      System.Console.WriteLine( _
          "Freezing point of water: {0}", _
          CInt(Temperatures.FreezingPoint))

      System.Console.WriteLine( _
           "Boiling point of water: {0}", _
           CInt(Temperatures.BoilingPoint))
   End Sub
End Module

When you cast a value (in this case, using the CInt function), you tell the compiler, “I know that this value is really of the indicated type.” In this case, you are saying, “Treat this enumerated constant as an Integer.” Since the underlying type is Integer, this is safe to do. See the section "Casting.”

Casting

Objects of one type can be converted into objects of another type. This is called casting , and casting can be either narrowing or widening.

A widening conversion or cast is one in which the conversion is to a type that can accommodate every possible value in the existing variable type. For example, an Integer can accommodate every possible value held by a Short. Casting from Short to Integer is, thus, a widening conversion.

A narrowing cast is one in which the conversion is to a type that may not be able to accommodate every possible value in the existing variable type. For example, a Short can accommodate only some of the values that an Integer variable might hold. Casting from an Integer to a Short is thus a narrowing conversion.

Visual Basic 2005 conversions are either implicit or explicit. In an implicit conversion, the compiler makes the conversion, with no special action by the developer. With an explicit conversion, the developer must use a special function to signal the cast. For example, in Example 16-4 you use the Cint function to explicitly cast the enumerated value to an Integer.

The semantics of an explicit conversion are “Hey! Compiler! I know what I’m doing.” This is sometimes called “hitting it with the big hammer” and can be very useful or very painful, depending on whether your thumb is in the way of the nail.

Whether a cast is implicit or explicit is affected by the Option Strict setting. If Option Strict is On (as it always should be) only widening casts can be implicit.

The explicit cast functions are:

CBool

Converts any valid string (e.g., “True”) or numeric expression to Boolean. Numeric nonzero values are converted to True; 0 is converted to False.

CByte

Converts numeric expression in range 0 to 255 to Byte. Rounds any fractional part.

CChar

Returns the first character of a string as a Char.

CDate

Converts any valid representation of a date or time to Date (e.g., “January 1, 2002” is converted to the corresponding Date type).

CDbl

Converts any expression that can be evaluated as a number to a Double if in the range of a Double.

CDec

Converts any expression that can be evaluated as a number to a Decimal if in the range of a Decimal.

CInt

Converts any expression that can be evaluated as a number to a Integer if in the range of a Integer, rounds fractional part.

CLng

Converts any expression that can be evaluated as a number to a Long if in the range of a Long, rounds fractional part.

CObj

Converts any expression that can be interpreted as an Object to an Object

CShort

Converts any expression that can be evaluated as a number to a Short if in the range of a Short

CStr

If Boolean, converts to the string “True” or “False.” If the expression can be interpreted as a date, returns a string expression of the date. For numeric expressions, the returned string represents the number.

CType

This is a general purpose conversion function that uses the syntax

CType(expression, typename)

where expression is an expression or a variable, and typename is the data type to convert to. The first conversion in Example 16-4:

System.Console.WriteLine( _
    "Freezing point of water: {0}", _
    CInt(Temperatures.FreezingPoint))

can be rewritten as:

System.Console.WriteLine( _
    "Freezing point of water: {0}", _
    CType(Temperatures.FreezingPoint, Integer))

The value in the enumerated constant is cast to an integer, and that integer value is passed to WriteLine and displayed. If you don’t specifically set it otherwise, the enumeration begins at 0 and each subsequent value counts up from the previous one.

If you create the following enumeration:

Enum SomeValues
   First
   Second
   Third = 20
   Fourth
End Enum

the value of First will be 0, Second will be 1, Third will be 20, and Fourth will be 21.

Tip

If Option Strict is set On, Enums are treated as formal types; that is, they are not just a synonym for another type, they are a type in their own right. Therefore, an explicit conversion is required to convert between Enum and an Integer types.

Strings

It is nearly impossible to write a Visual Basic 2005 program without creating strings . A string object holds a string of characters.

You declare a string variable using the String keyword much as you would create an instance of any object:

Dim myString as String

A string literal is created by placing double quotes around a string of letters:

"Hello World"

It is common to initialize a string variable with a string literal:

Dim myString as String = "Hello World"

Whitespace

In the Visual Basic 2005 language, spaces and tabs are considered to be whitespace (so named because you see only the white of the underlying “page”). Extra whitespace is generally ignored in Visual Basic 2005 statements. Thus, you can write:

Dim myVariable as Integer = 5

or:

Dim     myVariable     as     Integer     =     5

and the compiler will treat the two statements as identical.

The exception to this rule is that whitespace within strings is not ignored. If you write:

Console.WriteLine("Hello World")

each space between “Hello” and “World” is treated as another character in the string.

Most of the time, the use of whitespace is intuitive. The key is to use whitespace to make the program more readable to the programmer; the compiler is indifferent.

However, there are instances when the use of whitespace is quite significant. Although the expression:

Dim myVariable as Integer = 5 'no whitespace around = sign

is the same as:

Dim myVariable as Integer=5

it is not the same as:

DimmyVariable as Integer=5 'no white space around = sign

The compiler knows that the whitespace on either side of the assignment operator is extra, but the whitespace between the keyword Dim and the name of the variable is not extra, and is required.

This is not surprising; the whitespace allows the compiler to parse the keyword Dim rather than some unknown term DimmyVariable. You are free to add as much or as little whitespace between Dim and myVariable as you care to, but there must be at least one whitespace character (typically a space or tab).

Statements

In Visual Basic 2005, a complete program instruction is called a statement. Programs consist of sequences of Visual Basic 2005 statements . Each statement ends with a new line or a colon.

Dim myString As String = "Hello World"
Dim myVariable As Integer = 5 : Dim myVar2 As Integer = 7

Tip

The colon allows you to squeeze more than one statement on a single line, but is generally considered poor programming practice because it makes for code that is harder to read and thus harder to maintain.

If your code will not fit on a single line, you may use the line continuation character, the underscore: (_) to continue a single statement on more than one line, as shown here:

System.Console.WriteLine( _
    "Freezing point of water: {0}", _
    CInt(Temperatures.FreezingPoint))

All three lines are considered a single statement, because of the use of the line continuation character.

Tip

Be sure to add a space between any other code and the line continuation character.

Branching

Visual Basic 2005 statements are evaluated in order. The compiler starts at the beginning of a statement list and makes its way to the bottom. This would be entirely straightforward, and terribly limiting, were it not for branching .

Methods are executed from top to bottom. The compiler reads each line of code in turn, and executes one line after another. This continues in sequence until the method branches.

There are two ways a method can branch: unconditionally or conditionally. We’ll look at each of these in turn.

Unconditional Branching Statements

The most common way to branch is by calling a method. This is an unconditional branch.

You call a method by writing its name. For example:

Method1()  'invokes Method1

Tip

It is also legal to call a VB.NET method with the optional keyword call:

call Method1()

If you do use call on a function, the return value is discarded. There is no advantage to this syntax, and it isn’t used in this book.

Every time the compiler encounters a method call, it stops execution in the current method and branches to the newly called method. When that method returns, execution picks up in the original method on the line just below the method call, as illustrated schematically in Figure 16-2.

Branching schematic
Figure 16-2. Branching schematic

In Figure 16-2, execution begins in Main. Statements 1 and 2 execute and then the compiler sees a call to Method1. Program execution branches to the start of Method1, where its first three statements are executed. At the call to Method1A execution again branches, this time to the start of Method1A.

The four statements in Method1A are executed and Method1A returns. Execution resumes on the first statement after the method call in Method1 (Statement 4). Execution continues until Method1 ends, at which time execution resumes back in Main at Statement 3. At the call to Method2, execution again branches; all the statements in Method2 execute and then Main resumes at Statement 4. When Main ends, the program itself ends.

You can see the effect of method calls in Example 16-5. Execution begins in Main, but branches to a method named SomeMethod. The WriteLine statements in each method assist you in seeing where you are in the code as the program executes.

Example 16-5. Calling a method
Option Strict On
Option Explicit On

Module Module1
   Sub Main()
      Console.WriteLine("In Main! Calling SomeMethod...")
      SomeMethod()
      Console.WriteLine("Back in Main.")
   End Sub 'Main

   Sub SomeMethod()
      Console.WriteLine("Greetings from SomeMethod!")
   End Sub 'SomeMethod

End Module

Output:
In Main! Calling SomeMethod...
Greetings from SomeMethod!
Back in Main.

Program flow begins in Main and proceeds until SomeMethod is invoked (invoking a method is sometimes referred to as “calling " the method). At that point, program flow branches to the method. When the method completes, program flow resumes at the next line after the call to that method.

Tip

Another way to create an unconditional branch is with one of the unconditional branch keywords: goto, exit, return, or throw.

Conditional Branching Statements

While method calls cause unconditional branching, often you will want to branch within a method depending on a condition that you evaluate while the program is running. This is known as conditional branching.

Conditional branching statements allow you to write logic, such as “If you are over 25, then you may rent a car.”

If statements

The simplest branching statement is If. An If statement branches based on a condition. The condition is a Boolean expression.An expression is a statement that evaluates to a value. A Boolean expression evaluates to True or False.

An If statement says: if the condition evaluates to True, then execute the statement, otherwise, skip it. The formal description of an if statement is:

If expressionThen
   statements
End If

An alternative one-line version is:

If expression Then statement

The use of the If statement is illustrated in Example 16-6.

Example 16-6. The If statement
Option Strict On
Module Module1

   Sub Main()

      Dim valueOne As Integer = 10
      Dim valueTwo As Integer = 20
      Dim valueThree As Integer = 30

      Console.WriteLine("Testing valueOne against valueTwo...")
      If valueOne > valueTwo Then
         Console.WriteLine( _
             "ValueOne: {0} larger than ValueTwo: {1}", _
              valueOne, valueTwo)
      End If

      Console.WriteLine("Testing valueThree against valueTwo...")
      If valueThree > valueTwo Then
         Console.WriteLine( _
             "ValueThree: {0} larger than ValueTwo: {1}", _
              valueThree, valueTwo)
      End If

      Console.WriteLine("Testing is valueTwo > 15 (one line)...")
      If valueTwo > 15 Then Console.WriteLine("Yes it is")

   End Sub 'Main

End Module
Output:
Testing valueOne against valueTwo...
Testing valueThree against valueTwo...
ValueThree: 30 larger than ValueTwo: 20
Testing is valueTwo > 15 (one line)...
Yes it is

In this simple program, you declare three variables, valueOne, valueTwo, and valueThree. In the first If statement, you test whether valueOne is greater than valueTwo.

If valueOne > valueTwo Then
   Console.WriteLine( _
       "ValueOne: {0} larger than ValueTwo: {1}", valueOne, valueTwo)
End If

Because valueOne is less than valueTwo, this If statement fails (the condition returns False), and the body of the If statement (the statements between the If and the End If) never executes.

Tip

The test for greater than uses the greater-than operator (>), which is discussed in detail later in this chapter.

You then test whether valueThree is greater than valueTwo:

If valueThree > valueTwo Then
   Console.WriteLine( _
       "ValueThree: {0} larger than ValueTwo: {1}", valueThree, valueTwo)
End If

Since valueThree (30) is greater than valueTwo (20), the test returns True and thus the statement executes. The statement in this case is the call to WriteLine(), shown in bold.

Finally, Example 16-6 uses a one-line If statement to test whether valueTwo is greater than 15. Since this evaluates to True, the statement that follows executes, and the words “Yes it is” are displayed.

If valueTwo > 15 Then Console.WriteLine("Yes it is")

The output reflects that the first If statement fails, but the second and third succeed:

Testing valueOne against valueTwo...
Testing valueThree against valueTwo...
ValueThree: 30 larger than ValueTwo: 20
Testing is valueTwo > 15 (one line)...
Yes it is

Tip

Many Visual Basic 2005 developers avoid the single line If statement because it can be confusing and difficult to maintain.

If...Else statements

Often you will find that you want to take one set of actions when the condition tests True, and a different set of actions when the condition tests False. This allows you to write logic such as “If you are over 25, then you may rent a car; otherwise, you must take the train.”

The otherwise portion of the logic is executed in the else statement. For example, you can modify Example 16-6 to print an appropriate message whether or not valueOne is greater than valueTwo, as shown in Example 16-7.

Example 16-7. The Else clause
Option Strict On
Option Explicit On
Module Module1

   Sub Main()

      Dim valueOne As Integer = 10
      Dim valueTwo As Integer = 20
      Dim valueThree As Integer = 30

      Console.WriteLine("Testing valueOne against valueTwo...")
      If valueOne > valueTwo Then
         Console.WriteLine( _
             "ValueOne: {0} larger than ValueTwo: {1}", valueOne, valueTwo)
      Else
         Console.WriteLine( _
            "Nope, ValueOne: {0} is NOT larger than valueTwo: {1}", _
             valueOne, valueTwo)
      End If
   End Sub 'Main
End Module
Output:
Testing valueOne against valueTwo...
Nope, ValueOne: 10 is NOT larger than valueTwo: 20

Because the test in the If statement fails (valueOne is not larger than valueTwo), the body of the If statement is skipped and the body of the Else statement is executed. Had the test succeeded, the If statement body would execute and the body of the Else statement would be skipped.

It is possible, and not uncommon, to nest If statements one within another, to handle complex conditions. It is also common to evaluate a sequence of expressions with the ElseIf construct. The first If/ElseIf statement to evaluate True will have its statements executed (and no others will even be evaluated). If none of the statements evaluates True, the final Else clause is executed.

Select Case Statements

Nested If statements and long sequences of ElseIf statements are hard to read, maintain, and debug. When you have a complex set of choices to make, the Select Case statement is a more powerful alternative. The logic of a Select Case statement is to “pick a matching value and act accordingly.”

Select [ Case ] testExpression
[ Case expressionList
   [ statements ] ]
[ Case Else
   [ else statements] ]
End Select

It is easiest to understand this construct in the context of an example, as shown in Example 16-8.

Example 16-8. Select Case
Option Strict On
Module Module1

   Sub Main()
      Dim targetInteger As Integer = 15

      Select Case targetInteger
         Case 5
            Console.WriteLine("5")
         Case 10
            Console.WriteLine("10")
         Case 15
            Console.WriteLine("15!")
         Case Else
            Console.WriteLine("Value not found")
      End Select
   End Sub 'Main
End Module
Output:
15!

In Example 16-8, a value (15) is assigned to targetInteger. The Select Case statement tests for the values 5, 10 and 15. If one matches, the associated statement is executed. The output shows that the value 15 matched, and the associated statement was executed, displaying the value. If none of the values matched, the Else select statement would be executed.

Checking for a range of values

You can check for a range of values (e.g., Case 10 To 14).

You are not restricted to just testing for a numeric value. You can also test for String values, and you can test ranges of string values, examining whether a target value fits alphabetically within the range (e.g., Case “Alpha To Lambda”).

A single Case statement can test for more than one criterion: just separate them by commas:

Case "Fred", "Joe", Is < "Alpha"
   Console.WriteLine("Joe or Fred or < Alpha")

This case will match the strings “Fred” and “Joe” as well as any string that comes alphabetically before “Alpha.”

Iteration Statements

In a VB.NET method, you will find many situations in which you want to do the same thing again and again, perhaps slightly changing a value each time you repeat the action. This is called iteration or looping. Typically, you’ll iterate (or loop) over a set of items, taking the same action on each. This is the programming equivalent to an assembly line: take a hundred car bodies and put a windshield on each one as it comes by.

VB.NET provides an extensive suite of iteration statements , including Do and For.

The Do Loop

The semantics of a Do loop are “Do this work while a condition is true” or “Do this work until a condition becomes true.” You can test the condition either at the top or at the bottom of the loop. If you test at the bottom of the loop, the loop will execute at least once.

The Do loop can even be written with no conditions; in which case, it will execute indefinitely, until it encounters an Exit Do statement.

Do loops come in the following flavors:

Do While BooleanExpression
   statements
Loop

Do Until BooleanExpression
    statements
Loop

Do
    statements
Loop while BooleanExpression

Do
   statements
Loop until BooleanExpression

Do
    statements
Loop

In each case, the BooleanExpression can be any expression that evaluates to a Boolean value of True or False.

Do While

The first kind of Do loop, Do While, executes only while the BooleanExpression returns True, as shown in Example 16-9.

Example 16-9. Using Do While
Option Strict On
Module Module1

   Sub Main()
      Dim counterVariable As Integer = 0

      Do While counterVariable < 10
         Console.WriteLine("counterVariable: {0}", counterVariable)
         counterVariable = counterVariable + 1
      Loop ' While counterVariable < 10

   End Sub 'Main
End Module

Output:
counterVariable: 0
counterVariable: 1
counterVariable: 2
counterVariable: 3
counterVariable: 4
counterVariable: 5
counterVariable: 6
counterVariable: 7
counterVariable: 8
counterVariable: 9

Do Until

The second version of Do:

 Do Until BooleanExpression
    statements
Loop

executes until the BooleanExpression returns True.

Tip

Be very careful when looping to a specific value. If the value is never reached or is skipped over, your loop can continue without end, causing your program to “hang.”

The two constructs are closely related; which one you use will depend on the semantics of the problem you are trying to solve. That is, use the construct that represents how you think about the problem. If you are solving this problem: “keep winding the box until the Jack pops up,” then use a Do Until loop. If you are solving this problem: “As long as the music plays, keep dancing,” then use a Do While loop, though either construct will work (“keep dancing until the music stops.”)

The two variants:

Do
    statements
Loop while BooleanExpression

Do
   statements
Loop until BooleanExpression

are used when you want to ensure that the loop runs at least once, whatever the starting conditions. Thus, although your counterVariable might be initialized to 100, you want to make sure the loop runs once anyway. You’ll use the Do... Loop While construct.

Breaking out of a Do loop

You can break out of any Do loop with the Exit Do statement. You must break out of the final Do construct:

Do
    statements
Loop

because otherwise it will never terminate. You typically use this construct when you do not know in advance what condition will cause the loop to terminate (e.g., the termination may be in response to user action).

While Loops

As further proof that there are many ways to accomplish the same thing, VB.NET also offers a While loop construct that is closely related to the Do...While loops. The syntax is:

while BooleanExpression
  statements
End While

The For loop

When you need to iterate over a loop a specified number of times, you can use a For loop with a counter variable. The syntax of the For loop is:

For variable= expressionto expression [ step expression]
   statements
Next [ variable-list ]

The simplest and most common form of this statement creates a loop variable to count through the iterations of the loop. For example, you might create an integer variable loopCounter that you will use to step through a loop ten times, as shown in Example 16-10.

Example 16-10. For loop
Option Strict On
Module Module1

   Sub Main()

      Dim loopCounter As Integer
      For loopCounter = 0 To 9
         Console.WriteLine("loopCounter: {0}", loopCounter)
      Next

   End Sub 'Main

End Module
Output:
loopCounter: 0
loopCounter: 1
loopCounter: 2
loopCounter: 3
loopCounter: 4
loopCounter: 5
loopCounter: 6
loopCounter: 7
loopCounter: 8
loopCounter: 9

The variable (loopCounter) can be of any numeric type. For example, you might initialize a Single rather than an Integer, and step up through the loop from 0.5 to 9.

You can also modify multiple variables on each Next statement. This allows you to nest one For loop within another. You might use an outer and an inner loop to iterate through the contents of collections. A simple example of this technique is shown in Example 16-11.

Example 16-11. Multiple updates with one Next statement
Option Strict On
Module Module1

   Sub Main()

      Dim outer As Integer
      Dim inner As Integer

      For outer = 3 To 6
         For inner = 10 To 12
            Console.WriteLine("{0} * {1} = {2}", _
                outer, inner, outer * inner)
      Next 
 inner, outer

   End Sub 'Main

End Module

3 * 10 = 30
3 * 11 = 33
3 * 12 = 36
4 * 10 = 40
4 * 11 = 44
4 * 12 = 48
5 * 10 = 50
5 * 11 = 55
5 * 12 = 60
6 * 10 = 60
6 * 11 = 66
6 * 12 = 72

As an alternative to updating both counters in the same Next statement, you can provide each nested For loop with its own Next statement:

For outer = 3 To 6
    For inner = 10 To 12
       Console.WriteLine("{0} * {1} = {2}", _
           outer, inner, outer * inner)
    Next inner
 Next outer

When you update a single value in a Next statement, you are free to leave off the variable you are updating. Thus, the previous code is identical to this code:

For outer = 3 To 6
    For inner = 10 To 12
       Console.WriteLine("{0} * {1} = {2}", _
           outer, inner, outer * inner)
    Next
 Next

Tip

Using the variable name in Next statements is generally preferred by VB.NET programmers because it makes for code that is easier to understand and maintain.

Operators

An operator is a symbol (e.g., =, >, +) that causes VB.NET to take an action. That action might be assignment (=), addition of two values (+), or comparison of two values (>).

The simplest is the assignment operator:

myVariable = 15;

The single equal sign (=) is used to assign a value (15) to a variable (myVariable). If statements often use comparison operators :

if ( valueOne > valueTwo )

This If statement compares valueOne with valueTwo, and if the former is larger than the latter, the test evaluates True, and the If statement executes.

Arithmetic Operators

VB.NET uses seven arithmetic operators , six for standard calculations (+, −, *, ^, /, and ) and a seventh to return the remainder when dividing integers.

VB.NET offers two division operators: / and . The right-facing division operator (/) returns a floating-point answer. If you divide 12/5, the answer is 2.4, as you would expect. This answer is returned as a Double. If you assign the returned value to an Integer, the decimal part is lopped off, and the result will be 2. If Option Strict is On (as it should be), you cannot assign the result to an Integer without explicitly casting, because you would lose the decimal portion of the answer.

The left-facing division operator () returns an Integer value. If you divide 125, the result is returned with a truncated integer: 2. No cast is needed (even with Option Strict On) because you’ve explicitly asked for the integer value.

The modulus operator (Mod) modulus operator (Mod)

To find the remainder in integer division, use the modulus operator (Mod). For example, the statement 17 Mod 4 returns 1 (the remainder after integer division).

The modulus operator is more useful than you might imagine. When you perform modulus n on a number that is a multiple of n, the result is zero. Thus, 80 Mod 10 = 0 because 80 is an even multiple of 10. This allows you to set up loops in which you take an action every nth time through the loop, by testing a counter to see if Mod n is equal to zero.

The exponentiation (^) operator

The final arithmetic operator is the exponentiation operator , which raises a number to the power of the exponent:

2^8 = 1024 ' 2 to the 8th power is 1,024.

Relational Operators

Relational operators are used to compare two values, and then return a Boolean (True or False). The greater-than operator (>), for example, returns True if the value on the left of the operator is greater than the value on the right. Thus, 5 > 2 returns the value True, while 2 > 5 returns the value False.

The relational operators for VB.NET are shown in Table 16-5. This table assumes two variables: bigValue and smallValue, in which bigValue has been assigned the value 100 and smallValue the value 50.

Table 16-5. Relational operators assumes bigValue = 100 and smallValue = 50

Name

Operator

Given this statement

The expression evaluates to

Equals

=

bigValue = 100

bigValue = 80

True

False

Not Equals

<>

bigValue <> 100

bigValue <> 80

False

True

Greater than

>

bigValue > smallValue

True

Greater than or equals

>= or =>

bigValue >= smallValue

smallValue => bigValue

True

False

Less than

<

bigValue < smallValue

False

Less than or equals

<= or =<

smallValue <= bigValue

bigValue =< smallValue

True

False

Notice that some operators are composed of two characters. For example, greater than or equal to is created with the greater-than symbol (>) and the equal sign (=). You may place these symbols in either order (>= or =>)

The VB.NET equality operator (=) and assignment operator (=) use the same symbol.

When you write:

If myX = 5 Then myX = 7

the first use of the = symbol is the equality operator (if myX is equal to 5), the second use is the assignment operator (set myX to the value 7). The compiler figures out which is meant by context. (Eat your heart out, C# programmers!)

Use of Logical Operators with Conditionals

If statements test whether a condition is True. Often you will want to test if two conditions are both True, only one is True, or none is True. VB.NET provides a set of logical operators for this, as shown in Table 16-6. This table assumes two variables, x and y, in which x has the value 5 and y the value 7.

Table 16-6. Logical operators given x = 5 and y = 7

Operator

Given this statement

The expression evaluates to

Logic

And

x = 3 And y = 7

False

Both must be True, to evaluate True.

AndAlso

X = 3 AndAlso y = 7

False

Short circuits the test, y is never tested. If the left side fails, the right is not tested.

Or

x = 3 Or y = 7

True

Either or both must be True to evaluate True.

OrElse

X = 5 or y = 9

True

Short circuited, since x is equal to 5, no need to evaluate y.

Xor

X = 5 Xor y = 7

False

True only if one (and only one) statement is True.

Not

Not x = 3

True

Expression must be False for test to evaluate True.

The And operator tests whether two statements are both True. The first line in Table 16-6 includes an example that illustrates the use of the And operator:

x = 3 And y = 7

The entire expression evaluates False because one side (x = 3) is False.

With the Or operator, either or both sides must be True; the expression is False only if both sides are False. So, in the example in Table 16-6:

x = 3 Or y = 7

the entire expression evaluates to True because one side (y = 7) is True.

The Xor logical operator is used to test if one (and only one) of the two statements is correct. Thus:

x = 5 Xor y = 7

evaluates to False, because both statements are True. The Xor statement is False if both statements are True, or if both statements are False; it is True only if one and only one statement is True.

With a Not operator, the statement is True if the expression is False, and vice versa. So, in the accompanying example:

Not x = 3

the entire expression is True because the tested expression (x = 3) is False. (The logic is: “it is True that it is not True that x is equal to 3.”)

Operator Precedence

The compiler must know the order in which to evaluate a series of operators. For example, if I write:

myVariable = 5 + 7 * 3

there are three operators for the compiler to evaluate (=, +, and *). It could, for example, operate left to right, which would assign the value 5 to myVariable, then add 7 to the 5 (12) and multiply by 3 (36). Since we’re evaluating left to right, the assignment has been done, so the value 36 is thrown away. This is clearly not what is intended.

The rules of precedence tell the compiler which operators to evaluate first. As is the case in algebra, multiplication has higher precedence than addition, so 5 + 7 * 3 is equal to 26 rather than 36. Both addition and multiplication have higher precedence than assignment, so the compiler will do the math, and then assign the result (26) to myVariable only after the math is completed.

In VB.NET, parentheses are used to change the order of precedence much as they are in algebra. Thus, you can change the result by writing:

myVariable = (5+7) * 3

Grouping the elements of the assignment in this way causes the compiler to add 5 + 7, multiply the result by 3, and then assign that value (36) to myVariable.

Within a single line of code, operators are evaluated in the following order:

  • Parentheses

  • Arithmetic

  • Concatenation

  • Comparison

  • Logical

  • Assignment

Comparison operators are evaluated left to right. Arithmetic operators are evaluated in this order:

  • Exponentiation (^)

  • Division and multiplication (/, *)

  • Integer division ()

  • Modulo operator (Mod)

  • Addition and subtraction (+,−)

The logical operators are evaluated in this order:

  • Not

  • And

  • Or

  • Xor

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset