Chapter 5. Introducing Visual Basic .NET

Introducing Visual Basic .NET

In this chapter, you’ll learn:

The basic structure of Microsoft Visual Basic .NET.

How Visual Basic .NET differs from earlier forms of Visual Basic.

Just as ASP.NET is a much different beast than classic ASP, Visual Basic .NET differs considerably from its predecessors. For one thing, there’s no longer any difference in the Visual Basic that you use in ASP.NET pages and the Visual Basic that comes with the full Microsoft Visual Studio package. Visual Studio does provide an excellent graphical development environment, but you can use a text editor and get all the same Visual Basic language features. In other words, there’s no such thing as VBScript .NET, as opposed to Visual Basic 7 .NET. There’s just one Visual Basic .NET for everyone.

Lest euphoria overcome you, this one unified Visual Basic .NET is a considerable departure from all the versions of Visual Basic that came before it. Normal, incremental improvement accounts for some of this, but the main reason is compatibility with the common language runtime (known as the runtime). As you should recall from Chapter 2, the runtime provides a common run-time environment for all programs compiled by any .NET compiler. By implementing the runtime, Microsoft intends to end, once and for all, the situation in which some programming languages are much better than others for writing certain kinds of programs. This is a noble and worthwhile goal, but it does require a certain amount of uniformity among the various languages. Hence, Visual Basic has seen a staggering number of changes. For users of C++, there’s now a whole new language, called C#.

A complete guide to Visual Basic .NET is clearly beyond the scope of this book; in fact, it could fill several books. Nevertheless, this chapter provides a brief introduction to Visual Basic .NET, concentrating on fundamentals and on features that have changed. This information should be enough to get you started.

Remember Fuzzy Wuzzy, the bear who wasn’t fuzzy? Well, within ASP.NET, Visual Basic isn’t visual. It can’t display windows or dialog boxes, and when running within an ASP.NET page, it doesn’t even support MsgBox or InputBox functions. The reason for this is quite simple.

Because an ASP.NET page runs on the Web server, any dialog boxes it displayed would appear on the server’s console, inaccessible to the Web visitor. Of course, an ASP.NET page can write the HTML to create visual displays of any type on the Web visitor’s browser.

Coding Visual Basic .NET Statements

In general, Visual Basic statements begin anywhere on a line and end where the line ends. There are no semicolons, periods, or other punctuation at the end of a Visual Basic statement. Except within literals, any number of contiguous space or tab characters are equivalent to one space. Blank lines are irrelevant except for readability.

To continue a statement onto a second line, code a space and an underscore at the end of the continued line. The following code shows one statement continued across two lines:

lngZeta = lngAlpha + lngBeta + lngGamma _
    + lngDelta + lngEpsilon

With two exceptions, Visual Basic treats anything between an apostrophe and the end of a line as comments. The exceptions are as follows:

  • An apostrophe enclosed in quotation marks, as in this example, doesn’t mark the beginning of a comment:

    strReply = "No, I don't think so."
  • You can’t code comments after a continuation character. The following, for example, would be an error:

    lngZeta = lngAlpha + lngBeta + lngGamma _ ' Coffee break
        + lngDelta + lngEpsilon

Using Visual Basic Data Types

If you’re accustomed to using VBScript (the version of Visual Basic that classic ASP developers used), you’re accustomed to using only two data types: Variants and Objects. Well, in Visual Basic .NET, Microsoft has eliminated the Variant type, substituted Object as the default type, and then discouraged you from using the Object type. Instead, Microsoft encourages you to use the specific data types listed in the "Data Type Summary" table.

Data Type Summary

Category

Type

Bits

Bytes

LiteralTypeCharacter

TypicalValues

Character

Char

16

2

C

"A"C

 

String

   

"Bits"

Date

Date

64

8

#...#

#2/13/2002#

Decimal

Decimal

128

16

D

5.00D

Floating Point

Single

32

4

F

5.123S

 

Double

64

8

R

5.123R

Integer

Byte

1

1

 

0–255

 

Short

16

2

S

5S

 

Integer

32

4

I

5I

 

Long

64

9

L

5L

Logical

Boolean

16

2

 

True

     

False

Object

Object

32

4

  

To declare a variable, use the Dim statement as shown:

Dim strDescription As String
Dim intQuantity As Integer = 0
Dim booAnswer As Boolean = False

Specifying a value is optional. If you don’t assign a value when you declare a variable, Visual Basic assigns an empty string, zero, or false, depending on the data type.

Tip

Many Web developers find it valuable to begin the names of their variables with an abbreviation, one or three letters long, of the variable’s data type. This trick saves a lot of time otherwise spent debugging type conversion problems.

If you declare a variable without specifying a data type, Visual Basic makes the variable an Object. Later, when your code is running, an Object variable can refer to any of the other data types, but assigning or changing object types at run time (a practice called late binding or run-time binding) is a time-consuming operation. For this reason, it’s best to use specific data types when declaring variables.

Note

The opposite of late (or run-time) binding is early (or compile-time) binding. Early binding is preferable because the compiler can assemble much better code when it knows the exact type of each variable beforehand.

In all previous versions of Visual Basic, you didn’t need to code Dim statements for each variable unless you began the program or Web page with the statement:

Option Explicit

This is another area where Visual Basic .NET has changed: Option Explicit is now in effect unless you specifically turn it off. Don’t do this! The time and trouble of coding a Dim statement for each variable is nothing compared to the grief of debugging program code when a misspelled variable name provides an empty value where you expected real data. In addition, all Visual Basic variables not defined with a Dim statement are defined as Objects, and therefore incur the performance penalty of late binding. For more information about turning the Explicit option on or off, refer to "Coding the @ Page Directive" in Responding to Web Form Events in Chapter 3.

The following data types warrant particular mention:

  • String. This data type can accommodate strings as long as 2 billion double-byte characters. (The precise maximum length is 231-1.)

  • Date. All languages based on the .NET framework store dates as 64-bit integers. These represent dates ranging from January 1 of the year A.D. 1 to December 31, 9999, and times from 0:00:00 to 23:59:59.

    This additional capacity is a significant change from previous versions of Visual Basic, which stored dates as double-precision, floating-point values denoting days since December 30, 1899. Values to the left of the decimal represented the date, and values to the right of the decimal represented the time. Under this scheme, adding a week to a date was as simple as adding 7. Time flies, however, and with the new Visual Basic .NET date format, this technique no longer works. To manipulate dates, you must use the methods built into the .NET Date class. For more information about manipulating dates, refer to "Manipulating Dates" later in this chapter.

    • DecimalThis data type replaces the Currency type that was part of Visual Basic 6.

    • Short. This data type didn’t exist in Visual Basic 6. In Visual Basic .NET, it provides a way to declare 16-bit integers.

    • Integer. This data type is 32 bits in Visual Basic .NET. In Visual Basic 6, it was 16 bits.

    • Long. This data type is 64 bits in Visual Basic .NET. In Visual Basic 6, it was 32 bits.

    • Boolean. When you assign other numeric types to a Boolean value, 0 becomes False and all other values become True. When you assign Boolean values to other data types, False becomes 0 and True becomes 1.

    • Object. Don’t make the mistake of thinking that you must declare all your objects with a data type of Object. This approach works, but it forces the compiler to use late binding when your code runs and starts using the object. It’s much better to declare object variables with a specific object type. For example:

      Dim clrBlack as Color

      Most objects have a so-called constructor method that runs each time a program creates an object of the given type. If you defined three Color objects, for example, the constructor would run three times (once to initialize each object).

      If that’s not cool enough, most constructor methods can accept parameters from you, the developer—effectively initializing the object with any values you want. All you do is add the keyword New and parameters to your Dim statement:

      Dim dteGroundHog As New Date(2002, 2, 2)

If you declare several variables with a single Dim statement, all the variables will be the same type. In the following statement, for example, the lngJohn, lngTime, and lngGone variables will all be Long:

Dim lngJohn, lngTime, lngGone As Long

Previous versions of Visual Basic would designate lngJohn and lngTime as Variants and lngGone as Long.

Like Visual Basic 6 (and unlike VBScript), Visual Basic .NET supports user-defined types. These are basically structures that contain several variables of other types. You can access the whole structure as a single unit, or you can access its members individually.

A structure declaration consists of a Structure statement, then one or more member definitions, and then an End Structure statement. (Visual Basic 6 used a Type statement rather than a Structure statement.) Here’s an example:

Structure stcAddress
  Dim strStreet As String
  Dim strCity As String
  Dim strState As String
  Dim strPostCode As String
  Dim strCountry As String
End Structure

Once you’ve defined this structure, you can use it to define other variables. Suppose, for example, that you coded

Dim adrMyAddress As stcAddress
Dim adrYourAddress As stcAddress

You could then code statements such as

adrMyAddress.strStreet = "1600 Pennsylvania Avenue"
adrMyAddress.strCity = "Washington"
adrMyAddress.strState = "DC"
adrMyAddress.strPostCode = "20500"
adrMyAddress.strCountry = "USA"
adrYourAddress = adrMyAddress

Here’s the complete syntax for declaring a structure:

[Public|Private|Protected] Structure structname
  {Dim|Public|Private|Friend} member1 As datatype1
  ...
  {Dim|Public|Private|Friend} memberN As datatypeN
End Structure

The keywords Public, Private, Protected, and Friend control the degree of access to structures you define within a class. The table in Chapter 8 later in this chapter explains these keywords. Variables you declare without these keywords—using only the Dim keyword—are available everywhere within the region that contains the Dim statement. If a Dim statement is within a subroutine, the variable is available only within that subroutine. If a Dim statement is within a module, class, or structure, the variable is available anywhere within that module, class, or structure. For more information about defining classes, refer to "Defining Subroutines, Functions, and Classes" later in this chapter.

The following table lists the built-in functions Visual Basic .NET provides for converting one data type to another. These functions accept arguments of almost any data type and convert them to the types listed. If the conversion isn’t possible, the function will raise an exception.

Visual Basic .NET Type Conversion Functions

Result Data Type

Function

Description

Integer

Asc

Converts the first letter in a string to a number between 32768 and -32767 or, if the operating system doesn’t support double-byte characters, between 0 and 255.

Integer

AscW

Converts the first letter in a string to a number between 32768 and -32767.

Boolean

CBool

Returns False if the argument is zero and True otherwise.

Char

CChar

Returns the character corresponding to argument values 0–65535.

String

Chr

Returns the character corresponding to argument values 0–255 or, if the operating system supports double-byte characters, between -32768 and 65535.

String

CStr

Each of these functions converts an

Byte

CByte

expression to the data type in the first

Short

CShort

column. If the value of the expression

Integer

CInt

makes this impossible, an exception

Long

CLng

occurs. Attempting to evaluate the

DateTime

CDate

following expression, for example,

Single

CSng

will raise an exception:

Double

CDbl

CDate("personal ad")

Decimal

CDec

 

Object

CObj

 

Using Literals and Constants

Like most programming languages, Visual Basic .NET supports the use of literals. A literal is a value, such as 503, 2.5, or "doughnut", that you code in place of a variable. Literal values are read-only. You can’t change the value of 2 by coding a statement such as the following:

2 = 1 + 1 + 1

Constants are read-only named values. The following statement, for example, defines a constant named PSWD that’s equal to "sesame":

CONST PSWD = "sesame"

Having coded this statement, you could use the name PSWD instead of the value "sesame" in your code, making it easier to find and update the password when necessary. Constants are also a good solution when you use the same value several times in your code and it’s important that you code this value exactly the same way in each instance.

You can also use simple expressions to define the value of constants. The declarations below illustrate this:

CONST ENOUGH = 100
CONST TOO_MUCH = ENOUGH + 1

However, you can use only expressions that the compiler can evaluate at compile time. The following declaration would produce a compiler error because the compiler can’t predict what the value of Now() will be when the Web page actually runs:

CONST THE_DATE = Now()

Constants can also be part of the object model for controls or components you’re working with. Importing a namespace, for example, typically makes a large number of constants available to your ASP.NET page. Your code will be easier to read, easier to debug, and more accurate if you use the constants supplied for use with a certain method or property, rather than hard-coding values that have no obvious meaning. The documentation for the namespace, property, or method will list these constants.

Constants and literals in Visual Basic .NET have data types, just as variables do. The table below lists the default data types for various kinds of literals. The default data type for a constant is the data type of its literal.

Default Data Types For Literals

Type of value

Example

Data Type

Integral numbers

321

Integer

Floating-point numbers

3.12

Double

True or False

True

Boolean

Character values

"trouble"

String

Tip

To include quotation marks in a string literal, code two quotation marks where you want one to appear. The following code, for example, is valid:

strText = "Tom said, ""Sorry,"" but Anne wasn't impressed."

If you wish, you can also code the data type of a constant explicitly. The possibilities are Boolean, Char, String, Byte, Integer, Short, Long, DateTime, Single, Double, and Decimal. Here’s an example:

Public Const NORM_TEMP As Single = 37

There are at least three reasons for coding constant and literal types explicitly:

  • Explicitly declaring data types is unambiguous.

  • Typed code is easy to read and maintain.

  • When the Strict option is in effect, failing to declare a data type for a constant will produce a compiler error.

There are two ways to force the data type of a literal. For some data types, you enclose the literal value with special enclosing characters. For others, you append a special type character to the value. The enclosing characters and type characters for each data type are shown below. The literal 5S, for example, indicates a Short with a value of 5.

Visual Basic .NET Enclosing Characters and Type Characters

Data Type

Enclosing character

Appended type character

Boolean

(none)

(none)

Char

"

C

Byte

(none)

(none)

Short

(none)

S

Integer

(none)

I or %

Long

(none)

L or &

DateTime

#

(none)

Single

(none)

F or !

Double

(none)

R or #

Decimal

(none)

D or @

Visual Basic .NET provides the built-in constants listed in the table "Visual Basic .NET Print and Display Contents." These are frequently useful when you need to include nonprintable characters in an output stream. The notation Chr(13) means ASCII character 13, the carriage return.

Visual Basic .NET Print and Display Constants

Constant

Equivalent

Description

vbCrLf

Chr(13) & Chr(10)

Carriage return/linefeed character combination.

vbCr

Chr(13)

Carriage return character.

vbLf

Chr(10)

Linefeed character.

vbNewLine

Chr(13) & Chr(10)

New line character.

vbNullChar

Chr(0)

Character having value 0.

vbNullString

String having value 0

Not the same as a zero-length string (""); used for calling external procedures.

vbObjectError

-2147221504

Error number. User-defined error numbers should be greater than this value.

vbTab

Chr(9)

Tab character.

vbBack

Chr(8)

Backspace character.

vbFormFeed

Chr(12)

Not useful in Microsoft Windows.

vbVerticalTab

Chr(11)

Not useful in Microsoft Windows.

Using Operators

An operator is a symbol or keyword that tells Visual Basic to take action on one or more expressions. In the expression 1 + 2, for example, the + operator tells Visual Basic to add the two numbers. The next few sections describe the basic operators that Visual Basic.NET provides.

Using Arithmetic Operators

Visual Basic .NET, like all previous forms of Visual Basic, supports the arithmetic operators listed in the following table.

Visual Basic .NET Arithmetic Operators

Language Element

Description

^

Exponentiation

Subtraction

*

Multiplication

/

Floating-point division

Integer division

Mod

Integer remainder

+

Addition

The exponentiation and floating-point division operators always return a Double result. The others return the operand data type with the greatest range. To understand what this means, first consider the following order of ranges:

Byte, Short, Integer, Long, Single, Double, Decimal

If the operands of, say, an addition are a Byte and a Short, the result will be a Short. If the operands are a Long and a Decimal, the result will be a Decimal. The data type that can hold the largest number will be the data type of the result.

Using Assignment Operators

The assignment operator is, as always, the equal sign. To add the value of a variable named decUnitPrice to the value of a variable named decTotalPrice, you would code

decTotalPrice = decTotalPrice + decUnitPrice

In Visual Basic .NET, you can achieve the same result by coding

decTotalPrice += decUnitPrice

This second form adds the value of the expression on the right of the assignment operator to the variable you specify on the left. This form saves you the trouble of typing the receiving variable name twice. The same trick works for all these operators:

^=

Exponentiation

*=

Multiplication

/=

Floating-point division

=

Integer division

+=

Addition

-=

Subtraction

&=

Concatenation

Visual Basic .NET no longer supports the Set and Let statements. The Let statement has been extraneous for some time. Instead of coding

Let strThere = strLight

you can simply code

strThere = strLight

If you want two variables to point to the same object, code

objEct1 = objEct2

If you want objEct1 to point to a brand new object, code

objEct1 = New <object type> (<constructor params, if any>)

When you concatenate (that is, join) strings, you must always include spaces around the & operator. If you try to code an expression such as a&b& c, the compiler will report a syntax error and halt. You must code a & b & c.

Using Comparison Operators

Visual Basic .NET supports the comparison operators listed in the following table. If both operands are numeric, Visual Basic .NET compares them numerically. If one or both are characters or strings, Visual Basic .NET compares them as case-sensitive text.

Visual Basic .NET Comparison Operators

Comparison Operator

Description

=

Equal

<>

Not equal

<

Less than

>

Greater than

<=

Less than or equal

>=

Greater than or equal

Like

Matches pattern

Is

Returns True if both operands point to the same object.

The Like operator compares a string to a pattern. If the two match, the comparison is True; otherwise, of course, it’s False. If both the string and the pattern are empty, the result is True. If only one is empty, the result is False. The available patterns are listed in the following table.

Patterns For Comparisons Using the Like Operator

Characters in Pattern

Matches in String

?

Any single character

*

Zero or more characters

#

Any single digit (0–9)

[charlist]

Any single character in charlist

[!charlist]

Any single character not in charlist

Using the Like operator requires knowing its quirks and peculiarities. Here are some tips:

  • Visual Basic .NET compares a bracket expression in the pattern—no matter how long—to exactly one character position in the comparison string. The expression

    "abc" Like "a[xyzb]c"

    is true because a matches a, b matches one of the characters in xyzb, and c matches c.

  • To match the left bracket ([), question mark (?), number sign (#), and asterisk (*), enclose them in brackets. In the following example, the first expression is True because the asterisk matches any character. The second is False because "X" doesn’t equal the specific character *.

    "aaXaa" Like "aa*aa"
    "aaXaa" Like "aa[*]aa"
  • You can’t use the right bracket (])to match itself inside a group, but you can use it outside of a group as an individual character. The pattern ac[em]or]uv doesn’t match ac]uv, for example, because [em]or] isn’t a group that matches e, m, ], o, or r.

    The pattern ac[em]or]uv does match aceor]uv because [em] matches e.

  • To include a range of characters within the brackets, code the character with the lower sort order, a hyphen (-), and then the character with the higher sort order. The following expressions are equivalent:

    "A" Like "[0-9A-F]"
    "A" Like "[0123456789ABCDEF]"
  • If you code a hyphen as the first or last character within brackets, it matches only another hyphen character. The expression below is true because the hyphen is one of the characters in the first group and A is one of the characters in the second group.

    "-A" Like "[-02468][A-Z]"
  • An exclamation point (!) at the beginning of a bracketed group matches any character except those in the group. The first of the following expressions is True while the second is False:

    "void" Like "[!a-u]oid"
    "-oid" Like "[!-ad]oid"
  • Outside of any brackets, an exclamation point matches itself.

  • An empty group ([]) signifies an empty string ("").

Concatenating Strings

You can concatenate strings using either the plus (+) operator or the ampersand (&) operator. The following statements are equivalent:

strResult = "Welcome to " + "my circus."
strResult = "Welcome to " & "my circus."

Experienced Web developers, however, never use the plus (+) operator for joining strings. There are two very good reasons for this:

  • It’s very easy to code an expression such as a + b that you think will concatenate the variables a and b. However, if the variables are numeric, this expression actually adds them. The expression a & b always performs a concatenation.

  • Visual Basic .NET will halt with a compilation error if you use the plus (+) operator to concatenate a mixture of string variables and numeric variables. The ampersand (&) operator, however, does the same job without complaining at all.

In the end it comes down to this: use the concatenation operator (&) for concatenating and the addition operator (+) for adding. What could be easier than that?

Using Logical Operators

Visual Basic .NET uses the same logical operators as prior versions of Visual Basic, as well as two new ones, as listed in the following table.

Visual Basic .NET Logical Operators

Operator

Operands

Result

Not

1

True if operand is False

  

False if operand is True

And

2

True if both operands are True

  

False if either operand is False

Or

2

True if either operand is True

  

False if both operands are False

Xor

2

True if one operand is True

  

False if both operands are True or False

AndAlso

2

Same as And but short-circuited

OrElse

2

Same as Or but short-circuited

Most use of these operators involves Boolean operands, as shown in the following expression:

(lngOrderQty > 0) And (lngOnHandQty > 0)

The Not operand, when applied to a integer value, changes all the zero bits to one and all the one bits to zero. An integer value, in this case, means a value of type Byte, Short, Integer, or Long.

When used on integral operands, And, Or and Xor perform bitwise arithmetic. This applies the operator to the first bit of each operand, then to the second bit of each operand, and so forth.

To understand the difference between And and AndAlso, consider the following expression:

IsNumeric(strQuantity) And (clng(strQuantity) > 0)

Visual Basic uses the following procedure to evaluate this expression:

  1. Determine whether Visual Basic .NET can convert the value in strQuantity to a number. If this conversion is possible, return True. Otherwise, return False.

  2. Convert the value in strQuantity to a Long integer and compare the result to zero. If the result is greater than zero, return True. If it’s less than or equal to zero, return False.

  3. Examine the results from steps 1 and 2. If both are True, return True. Otherwise, return False.

This situation presents a problem because if strQuantity contains a nonnumeric value such as xyz, executing the expression clng(strQuantity) will throw an exception. Web developers in the past solved this by nesting If statements as shown here:

If IsNumeric(strQuantity) Then
    If (clng(strQuantity) > 0) Then
'       Code that does the work goes here.
    End If
End If

But the new AndAlso operator provides a more elegant solution:

IsNumeric(strQuantity) AndAlso (clng(strQuantity) > 0)

This code tells Visual Basic .NET that if IsNumeric(strQuantity) turns out to be False, it shouldn’t bother evaluating (clng(strQuantity) > 0). After all, if the first operand of an And expression is False, the entire And expression will be False no matter the state of the second operand.

Similarly, the OrElse operator skips evaluating the second operand if the first operand is True. If the first operand of an Or expression is True, the entire Or expression will be True no matter the state of the second operand.

Using Miscellaneous Operators

The AddressOf operator returns the address of a subroutine or function. This is a useful tool for situations in which you must supply the address of a procedure that ASP.NET will call when a specific event occurs.

The GetType operator returns the type object of the specified type. The expression GetType(Integer), for example, returns the base object that defines the entire Integer class. This expression can be useful for getting various information about the type, such as its properties, methods, and events.

Manipulating Dates

Visual Basic .NET stores times and dates in the same way as all other .NET languages and components. Specifically, they’re 64-bit integers that count the number of 100-nanosecond "ticks" since midnight, Coordinated Universal Time, January 1 of the year 1 in the Gregorian calendar. The time value for one second after midnight on 1-Jan-0001 is 10,000,000.

Note

Coordinated Universal Time (UTC) is what you probably know as Greenwich Mean Time (GMT). Coordinated Universal Time, however, is the newer term that Microsoft uses in all its documentation.

Previous versions of Visual Basic stored dates as floating-point numbers. The integer part counted the number of days since December 30, 1899, and the fractional part represented a time of day. The number 2.25, for example, meant January 1, 1900, at 6:00 A.M. This system made it easy to determine the difference in days between two dates, to add 7 days to a certain date, and so forth. Unfortunately, these sorts of computations no longer produce meaningful results. Adding 7 to a date in the new DateTime format adds 700 nanoseconds.

DateTime comparisons such as greater than and less than still work reliably. Equality comparisons work too, provided that the margin of error is less than 100 nanoseconds.

You can specify DateTime values in code either by enclosing a suitably formatted string in number signs or by using the DateTime constructor method. The following pairs of statements are equivalent:

Dim dtmDateDue as DateTime = #12/31/2002#
Dim dtmDateDue as New DateTime(2002, 12, 31)

dtmDateDue = #12/31/2002#
dtmDateDue = New DateTime(2002, 12, 31)

dtmDateDue = #12/31/2002 1:30 PM#
dtmDateDue = New DateTime(2002, 12, 31, 13, 30, 0)

When you use the DateTime constructor method, you can specify one, three, six, or seven arguments. These have the following significance:

  • 1 Ticks

  • 3 Year, Month, Day

  • 6 Year, Month, Day, Hour, Minute, Second

  • 7 Year, Month, Day, Hour, Minute, Second, Millisecond

In addition to changing the date format, Visual Basic .NET drops support for several date functions that earlier versions of Visual Basic have supported for some time. These legacy functions, along with the comparable Visual Basic .NET functions, are listed in the table below.

Date Functions Dropped in Visual Basic .NET

Legacy Function

Visual Basic .NET Replacement

Type

Comments

Date

Today

DateTime

Gets or sets the system date.

Date$

DateString

String

Gets or sets the system date.

Time

TimeOfDay

DateTime

Gets or sets the system time.

Time$

TimeString

String

Gets or sets the system time.

Now

Now (note)

DateTime

Gets the system date and time.

Timer

Timer(note)

Single

Gets the number of seconds elapsed since midnight.

Note

In Visual Basic .NET, these keywords identify properties rather than functions.

Visual Basic .NET continues to support all the remaining date and time functions shown in the following table, taking the new DateTime format into account as necessary.

Date Functions Retained in Visual Basic .NET

Result Type

Name

Description

Argument Type

Boolean

IsDate

Indicates whether Visual Basic .NET can convert an expression to a date.

String

DateTime

DateAdd

Adds a specified interval.

DateTime

DateTime

DateSerial

Returns the DateTime value for a given year, month, and day.

Integers

DateTime

TimeSerial

Returns the DateTime value for a given hour, minute, and second.

Integers

DateTime

TimeValue

Returns the DateTime value for a given time.

String

DateTime

DateValue

Returns the DateTime value for a given date.

String

Integer

DatePart

Returns the specified part of a given date.

DateTime

Integer

Year

Returns the year.

DateTime

Integer

Month

Returns the month of the year.

DateTime

Integer

Day

Returns the day of the month.

DateTime

Integer

Hour

Returns the hour of the day.

DateTime

Integer

Minute

Returns the minute of the hour.

DateTime

Integer

Second

Returns the second of the minute.

DateTime

Integer

Weekday

Returns the day of the week.

DateTime

Long

DateDiff

Returns the number of intervals between two dates. You can specify intervals of minutes, days, years, and so forth.

Strings, DateTime

String

MonthName

Returns the name of a given month.

Integer

String

WeekdayName

Returns the name of a given day of the week.

Integer

If none of these functions serve your needs, then perhaps one of the many date and time functions built into the .NET Framework will help. For starters, the following expressions return the minimum and maximum permissible date values:

DateTime.MaxValue
DateTime.MinValue

Using the methods listed in the table "DateTime Public Static (Shared) Methods" requires a similar notation. The following expression, for example, returns False because the year 2100 won’t be a leap year:

DateTime.IsLeapYear(2100)

DateTime Public Static (Shared) Methods

Result type

Name

Description

Argument Type

Compare

Integer

Compares two DateTime objects and returns -1, 0, or +1, depending on their relative values.

DateTimes

DaysInMonth

Integer

Returns the number of days in the specified year and month.

Integers

Equals

Integer

Indicates whether two variables point to the same DateTime object.

DateTimes

FromFileTime

DateTime

Returns the DateTime value that corresponds to an operating system file time stamp.

Long

FromOADate

DateTime

Returns a DateTime equivalent to the specified OLE Automation Date.

Double

IsLeapYear

Boolean

Indicates whether a given year is a leap year.

Integer

Parse

DateTime

Converts a String to its DateTime equivalent.

String

ParseExact

DateTime

Converts a String to its DateTime equivalent. The format of the String representation must exactly match a specified format.

String

If you still haven’t found a function that meets your needs, consider the DateTime properties listed in the "DateTime Public Instance Properties" table. These properties are available for every DateTime object. If the variable dtmDateDue is a DateTime value, the following expressions return its year, month, day, hour, and minute values:

dtmDateDue.Year
dtmDateDue.Month
dtmDateDue.Day
dtmDateDue.Hour
dtmDateDue.Minute

DateTime Public Instance Properties

Result Type

Property

Description

DateTime

Date

Gets the date component.

DateTime

TimeOfDay

Gets the time-of-day component.

Integer

Year

Gets the year component.

Integer

Month

Gets the month component.

Integer

Day

Gets the day of the month.

Integer

Hour

Gets the hour component.

Integer

Minute

Gets the minute component.

Integer

Second

Gets the seconds component.

Integer

Millisecond

Gets the milliseconds component.

Integer

DayOfWeek

Gets the day of the week.

Integer

DayOfYear

Gets the day of the year.

Long

Ticks

Gets the number of 100-nanosecond ticks that represent the date and time.

Visual Basic .NET aims to please. If, by some incredible chance, none of the preceding functions or properties meet your important date-processing needs, one of the methods listed in the next table might be just the ticket. To use these methods, code the name of a DateTime object, a period, the method name, and then (in parentheses) any required arguments. Both of the following statements, for example, add seven days to the DateTime variable dtmDateDue. To subtract an interval, use an Add method and specify a negative amount.

dtmDateDue.Add(TimeSpan.FromDays(7))
dtmDateDue.AddDays(7)

The ToLocalTime and ToUniversalTime methods warrant a bit of additional explanation. By default, the starting point for all DateTime values is midnight, Coordinated Universal Time. Using this starting point eliminates endless confusion when computers in different time zones exchange dates, particularly in real time over a network.

The fact that dates on your computer are actually in UTC is almost never apparent because all the standard date functions automatically convert UTC to your local time zone, based on settings in the Windows Control Panel. This behind-the-scenes step eliminates any need to use the ToLocalTime and ToUniversalTime methods in ordinary software applications. However, if you do find a need to make these conversions, the necessary methods are ready and waiting.

DateTime Public Instance Methods

Result Type

Member

Description

DateTime

Add

Adds the value of a given TimeSpan instance.

DateTime

Subtract

Subtracts the value of a given TimeSpan instance.

DateTime

AddYears

Adds the specified number of years.

DateTime

AddMonths

Adds the specified number of months.

DateTime

AddDays

Adds the specified number of days.

DateTime

AddHours

Adds the specified number of hours.

DateTime

AddMinutes

Adds the specified number of minutes.

DateTime

AddSeconds

Adds the specified number of seconds.

DateTime

AddMilliseconds

Adds the specified number of milliseconds.

DateTime

AddTicks

Adds the specified number of ticks.

DateTime

ToLocalTime

Converts the current coordinated universal time (UTC) to local time.

DateTime

ToUniversalTime

Converts the current local time to coordinated universal time (UTC).

Integer

CompareTo

Compares the current DateTime object to another and returns -1, 0, or +1, depending on their relative values.

Integer

Equals

Indicates whether another variable points to the same DateTime object as the current variable.

Long

ToFileTime

Converts the DateTime value to the format of the local system file time.

String

ToLongDateString

Formats the DateTime value as specified by the operating system’s Long Date setting.

String

ToLongTimeString

Formats the DateTime value as specified by the operating system’s Long Time setting.

String

ToShortDateString

Formats the DateTime value as specified by the operating system’s Short Date setting.

String

ToShortTimeString

Formats the DateTime value as specified by the operating system’s Short Time setting.

String

ToString

Formats the DateTime value as an equivalent string.

Double

ToOADate

Converts the value of this instance to the equivalent OLE Automation date.

Manipulating Strings

String handling is a major part of the processing that goes on in most Web pages. The simple reason is that most data consists of strings.

Previous sections described how to define string constants, literals, and variables; concatenate strings; and assign the value of a string expression to another. These are worthwhile operations, but they don’t address common requirements such as the need to split, join, and otherwise modify string data. For such operations, Visual Basic .NET provides the functions listed in the following table.

Visual Basic .NET String Handling Functions

Result Type

Function

Description

Integer

StrComp

Compares two strings and returns the result.

Long

Len

Returns the number of characters in a string or the number of bytes required to store a variable.

Long

InStr

Returns the position of one string within another.

Long

InStrRev

Returns the position of one string within another, searching from the end of string.

Char

GetChar

Returns the character from the specified index in the supplied string.

String

Mid

Returns a specified number of characters from a specified position within the argument string.

String

Left

Returns a specified number of characters from the left side of a string.

String

Right

Returns a specified number of characters from the right side of a string.

String

Ltrim

Returns the argument string with leading spaces removed.

String

Rtrim

Returns the argument string with trailing spaces removed.

String

Trim

Returns the argument string with leading and trailing spaces removed.

String

LCase

Converts the argument string to lowercase.

String

UCase

Converts the argument string to uppercase.

String

StrConv

Converts the argument string to a different case or character width.

String

StrReverse

Reverses the order of the characters in the argument string.

String

RSet

Returns the argument string with spaces added at the beginning, so that the string is a specified length and will be right-aligned with other strings of the same length.

String

LSet

Returns the argument string with spaces added at the end, so that the string is a specified length and will be left-aligned with other strings of the same length.

String

Replace

Replaces one substring with another a specified number of times.

String

Space

Returns a specified number of spaces.

String

StrDup

Returns the argument character repeated a specific number of times.

String

String

Returns a repeating character string of the length specified.

Working with Arrays

Like all previous versions of Visual Basic, Visual Basic .NET supports arrays. An array, in this sense, is a series of variables, each identified by the same name but a different index number. Arrays make it easy for a program to loop through and process each variable the array contains.

Unlike previous versions of Visual Basic, Visual Basic .NET supports arrays not with its own built-in code, but through the .NET Framework’s System.Array object. This change means, for example, that when you define an array in Visual Basic .NET, you’re actually defining a .NET System.Array object. When you write traditional Visual Basic statements and expressions that process the array, Visual Basic .NET works behind the scenes and invokes System.Array properties and methods.

The fact that Visual Basic .NET implements arrays as .NET objects makes it simple to pass arrays among Visual Basic .NET modules, modules written in different programming languages, and .NET objects and interfaces of all kinds. Of course, this ease comes at a price; compared to previous versions, there are quite a few differences in the way Visual Basic .NET handles arrays.

The statement that defines a normal array hasn’t changed unless you’re accustomed to working with VBScript. The following statement, for example, defines an array of 12 integers named Month:

Dim Month(12) As Integer

In Visual Basic .NET, the following forms of declaration are also permissible. All three statements produce the same results, except that the last statement also puts values into the array.

Dim Month() As Integer = New Integer(12) {}
Dim Month() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

Tip

Visual Basic allocates memory for all possible elements at the time you define an array. Therefore, don’t make arrays any larger than necessary.

If you’re accustomed to VBScript, you’re probably not accustomed to specifying the As keyword followed by a data type. This data type applies to each element of the array. Given that all other variable declarations require data types, however, the need to specify a data type for arrays should be no surprise. The permissible data types include

  • Any of the fundamental data types

  • Any structure

  • Any object class

Tip

When an array’s data type is Object, its elements can contain different kinds of data (objects, strings, numbers, and so forth).

In earlier versions of Visual Basic, you could define arrays that started with a subscript other than zero. This is no longer possible. Another difference is that when you code a statement such as

Dim Month(12) As Integer

Visual Basic .NET creates an array with 12 elements (the number you specified) subscripted 0 through 11. Earlier versions created 13 elements subscripted 0 through 12. If you try to access Month(12) in your code, Visual Basic .NET will throw a fit (oh, all right: an exception).

Visual Basic .NET arrays can have from one to 60 dimensions. The number of dimensions determines the array’s rank. An array of rank 3 would have three dimensions and its index would have three subscripts, as in cubicle(2, 4, 6). Most arrays have one dimension, and arrays of more than three dimensions are extremely rare.

All Visual Basic .NET arrays are variable-length, which doesn’t mean Visual Basic .NET automatically creates array elements when you access an out-of-bounds subscript. It does mean you can use the ReDim statement on any array whenever you want. The only restrictions are as follows:

  • You can’t use the ReDim statement to initially declare an array. Use Dim to declare the array and ReDim to modify it.

  • You can change the length of any dimension you want, but you can’t change the data type or the number of dimensions.

  • If you want to preserve existing data in the array, you can resize only the last dimension.

The following statement, for example, would expand the length of the Month table from 12 to 24. It would then support subscripts 0 through 23. It doesn’t matter which form of the Dim statement you used when you declared the array.

ReDim Preserve Month(24)

Tip

Whenever your code executes a ReDim statement, it first creates a completely new array, then copies over any existing array elements, and then deletes the first array. This process is expensive enough, in terms of resources, that you should avoid executing ReDim statements often. For example, don’t ReDim an array one element larger every time you want to store a value.

The fact that Visual Basic .NET array variables point to a System.Array object has the following implications:

  • An array variable that you declare in your ASP.NET page is actually a pointer to an object that contains the array’s rank, length, and element information.

  • Arrays have the same data type only if they have the same rank and the same element data type.

  • When you assign one array to another, Visual Basic .NET copies only the pointer. Consider, for example, the following block of statements:

    Dim strHomeTeam() As String = {"Xavier","Yves","Zebediah"}
    Dim strVisitors() As String = {"Abby","Bryony","Cleo"}
    strHomeTeam = strVisitors
    strVisitors(0) = "Maeko"

    After Visual Basic .NET executes these statements, both strVisitors(0) and strHomeTeam(0) will equal Maeko because the statement on line 3 makes strHomeTeam point to the same table object as strVisitors. The table object that strHomeTeam originally addressed was lost.

When you assign one array variable to another, Visual Basic .NET will enforce the following rules during compilation and at run time:

  • Either both arrays must have reference type elements (that is, objects) or both arrays must have value type elements (that is, integers, strings, and other elementary data types).

  • If both arrays have value type elements, the element data types must be exactly the same. The following generates an error:

    Dim lngNumbers(10) As Long
    Dim strLetters(10) As String
    strLetters = lngNumbers
  • If both arrays have reference type elements, there must be a widening conversion from the source element type to the destination element type.

  • The rank (number of dimensions) of the source and destination arrays must be the same.

  • Although the ranks of the two arrays must be equal, the dimensions don’t. The length of any dimension in the destination array can change.

Like older versions of Visual Basic, Visual Basic .NET provides the array-related functions listed in the next table. The Ubound function in particular is worth noting because it always returns an up-to-date value for the maximum subscript of a table. Suppose, for example, that you defined the following table:

Dim strNames As String = {"Bill", "Mary", "Tom", "Wendy"}

If you assumed elsewhere in your code that this table contained four elements, the code would malfunction if some other part of your code changed the size of the array by using a ReDim or assignment statement. It’s much better to assume that the array contains Ubound(strNames) + 1 elements numbered 0 through Ubound(strNames).

Visual Basic .NET Array Functions

Result Type

Function

Description

Array

Filter

Returns a subset of a string array containing only those elements that contain (or don’t contain) a specified string.

Array

Split

Converts a delimited string into a one-dimensional array, based on the specified delimiter.

Boolean

IsArray

Indicates whether a variable is an array.

Long

Lbound

Returns the smallest available subscript for the indicated dimension of an array. In Visual Basic .NET, this is always zero.

Long

Ubound

Returns the largest available subscript for the indicated dimension of an array.

String

Join

Converts an array into a delimited string, inserting the specified delimiter between the values of each former array element.

Because Visual Basic .NET arrays inherit from the Array class in the System namespace, you can use System.Array methods and properties on any Visual Basic .NET array. The second statement in the following example displays the array’s rank. The third sorts the array based on the values in its elements.

Dim strAnimals() As String = {"Crocodile","Bison","Aardvark"}
Response.Write(strAnimals.Rank)
Array.Sort(strAnimals)

The following table lists a number of useful functions that the System.Array object provides. Note that these are methods of the System.Array object itself, and not of individual arrays. You specify the array you want to process as an argument.

Common System.Array Public Static Methods

Method Type

Result Type

Method

Description

Function

Integer

Array.BinarySearch

Searches a one-dimensional sorted array for a value, using a binary search algorithm.

Function

Integer

Array.IndexOf

Sequentially searches all or part of a one-dimensional array for a given value, starting from the lowest applicable index.

Function

Integer

Array.LastIndexOf

Sequentially searches all or part of a one-dimensional array, starting from the highest applicable index.

Sub

 

Array.Clear

Sets a range of array elements to Nothing.

Sub

 

Array.Copy

Copies a section of one array to another and performs type downcasting as required.

Sub

 

Array.Reverse

Reverses the order of elements in all or part of a one-dimensional array.

Sub

 

Array.Sort

Sorts the elements of a one-dimensional array.

To look up the calling sequence for these methods, as well as for properties and methods in the next two tables, search the MSDN Web site (msdn.microsoft.com/library) for the term NET Framework Class Library and then search within the results for the terms System, Array Class, and Members.

The "Common System.Arrray Properties" table lists the Rank property (already discussed) and the Length property, which returns a count of elements in all dimensions of an array. For most Visual Basic Web developers, the Length property of an array is something to avoid. To see why, consider the following array:

Dim TwoDim(10, 20)

The expression TwoDim.Length returns 231, which is the product of 11 × 21. The expressions Ubound(TwoDim, 1) and Ubound(TwoDim, 2), which return 10 and 20, are far more useful.

Common System.Array Properties

Result Type

Method

Description

Long

Length

Returns the total number of elements in all dimensions of an array.

Long

Rank

Returns the rank (number of dimensions) of an array.

Each Visual Basic .NET array inherits the System.Array methods listed in the "Common System.Array Methods" table.

Common System.Array Methods

Method Type

Result Type

Method

Description

Function

Array

Clone

Creates a new array that points to the same elements as the original array.

Function

Boolean

Equals

Determines whether two object instances are equal.

Function

Integer

GetLength

Gets the number of elements in the specified dimension of an array. This value exceeds by one the number of elements available to Visual Basic .NET.

Function

Integer

GetLowerBound

Gets the lower bound of the specified dimension in the array. This is always zero.

Function

Integer

GetUpperBound

Gets the upper bound of the specified dimension in the array. This value equals the number of elements available to Visual Basic .NET.

Function

Type

GetType

Gets the type of an array. Compare the result to an expression such as GetType(String).

Function

Array Type

GetValue

Gets the values of the array elements at the specified indexes.

Sub

 

SetValue

Sets the specified array element to the specified value.

Sub

 

CopyTo

Copies all the elements of a one-dimensional array to another starting at a specified destination index.

To use these methods, you append their names to the name of the array you want them to process. Here’s an example:

strVisitors.CopyTo(strHomeTeam,0)

This statement copies all the elements of the strVisitors array into the strHomeTeam array, starting at position 0 of the strHomeTeam array. Unlike the assignment statement strHomeTeam = strVisitors, the CopyTo method actually copies each element of the source array. The source and destination array variables don’t end up being aliases of the same physical table. However, the CopyTo method has its own quirks:

  • It works only on one-dimensional arrays.

  • It can’t resize the destination array.

  • At least in early versions, and despite the previous statement, it has the unfortunate effect of adding one empty element to the end of the destination array.

For the most part, the remaining methods perform functions that the Visual Basic .NET functions listed in the previous table also provide. In general, the Visual Basic .NET functions are more reliable and easier to use.

Using Collections

Arrays, which have been features of most programming languages since the early years of computing, provide an excellent way to process collections of data in a repetitive manner. For some jobs, however, the inherent structure of arrays makes them a poor fit. This is particularly true of collections that contain a continually variable number of items and collections where the natural identifier is alphabetic rather than numeric.

VBScript provides a Scripting.Dictionary object that meets these needs to a large extent. Basically, a programmer working in VBScript can add, update, and delete items in a Scripting.Dictionary object at will, and each item has an alphanumeric identifier. This object is often useful when using an array would be awkward, but it doesn’t keep its entries in order by key value. In other words, it doesn’t accommodate situations where you need a variable number of numeric keys or where you need alphanumeric keys kept in order.

To resolve these issues in Visual Basic .NET, Microsoft chose not to implement a .NET version of the Scripting.Dictionary object, but to implement the following objects instead:

  • ArrayList. This object stores a collection of values in a variable-length list and identifies them by numeric position. An ArrayList containing 10 items, for example, would identify them as 0–9. If you deleted the fifth item, the remaining items would be 0–8.

  • Hashtable. This object holds a collection of string keys and associated values organized by a hash code of the key. (A hash code is an arbitrary value calculated from some other value such as, in this case, the item key.) A Hashtable stores the keys in random order and is thus the most comparable of these objects to the Scripting.Dictionary.

  • SortedList. This object works very much like a Hashtable, except that it keeps its keys in alphanumeric order. As with the Hashtable, you can access the values in a SortedList by alphanumeric key. As with the ArrayList, you can also access the values by numeric position. Finally, you can access the key values in a SortedList by numeric position as well.

  • Queue. This object stores a collection of items and returns them in first-in, first-out order.

  • Stack. This object stores a collection of items and returns them in last-in, first-out order.

Although tables and collections can both store structures and objects, the ADO.NET DataTable is much better suited to handling data records. For more information about DataTables, refer to Chapter 7.

To add one of these objects to your Web page, simply declare it as shown:

Dim arlNames As New ArrayList
Dim htbNames As New Hashtable
dim stlNames As New SortedList
dim queNames As New Queue
dim stkNames As New Stack

The table ".NET Collection Methods" summarizes the methods available for each object type, and ".NET Collection Properties" summarizes the properties. To the extent possible, Microsoft has implemented the same properties and methods for all five collections. All five objects, for example, have a Count property that reports the number of items the object currently stores.

.NET Collection Methods

Method

Description

Array List

Hash table

Sorted List

Queue

Stack

Add

Adds an entry to the collection.

X

X

X

BinarySearch

Uses a binary search to locate a specific element.

X

Clear

Removes all elements from the collection.

X

X

X

X

X

Clone

Creates a shallow copy of the collection.

X

X

X

X

X

Contains

Determines whether an element is in the collection.

X

X

X

X

X

ContainsKey

Determines whether the collection contains a specific key.

X

X

ContainsValue

Determines whether the collection contains a specific value.

X

X

CopyTo

Copies all or part of a collection to a one-dimensional array.

X

X

X

X

X

Dequeue

Removes and returns the object at the beginning of the Queue.

X

Enqueue

Adds an object to the end of the Queue.

X

GetByIndex

Gets the value at the specified index of the SortedList.

X

GetKey

Gets the key at the specified index of the SortedList.

X

GetKeyList

Gets the keys in the SortedList.

X

GetObjectData

Implements the ISerializable interface and returns the data needed to serialize the Hashtable.

X

GetRange

Returns an ArrayList that represents a subset of the elements in the source ArrayList.

X

GetType

Gets the Type of the current instance.

X

X

X

X

X

GetValueList

Gets the values in the SortedList.

X

IndexOf

Returns the zero-based index of the first occurrence of a value in the ArrayList or in a portion of it.

X

IndexOfKey

Returns the zero-based index of the specified key in the SortedList.

X

IndexOfValue

Returns the zero-based index of the first occurrence of the specified value in the SortedList.

X

Insert

Inserts an element into the ArrayList at the specified index.

X

InsertRange

Inserts the elements of a collection into the ArrayList at the specified index.

X

LastIndexOf

Returns the zero-based index of the last occurrence of a value in the ArrayList or in a portion of it.

X

Peek

Returns the object at the beginning or top of the collection without removing it.

X

X

Pop

Removes and returns the object at the top of the Stack.

X

Push

Inserts an object at the top of the Stack.

X

Remove

Removes an entry from the collection.

X

X

X

RemoveAt

Removes the element at the specified index of the collection.

X

X

RemoveRange

Removes a range of elements from the ArrayList.

X

Reverse

Reverses the order of the elements in the ArrayList or a portion of it.

X

SetByIndex

Replaces the value at a specific index in the SortedList.

X

SetRange

Copies the elements of a collection over a range of elements in the ArrayList.

X

Sort

Sorts the elementsin the ArrayList or a portion of it.

X

ToArray

Copies collection elements to a new array.

X

X

X

TrimToSize

Sets the capacity to the actual number of elements in the collection.

X

X

The Add method adds an item to an ArrayList, Hashtable, or SortedList collection.

  • For ArrayLists, the Add method accepts only a value; the ArrayList increases the size of the collection by one and adds the new entry at the end. Here are two examples:

    arlNames.Add("Abrienda")
    intPos = arlNames.Add("Bryony")

    After executing the second statement, the variable intPos contains the new entry’s index value.

  • For Hashtables and SortedLists, the Add method expects both a key and a value.

    • A Hashtable collection adds the item in random order.

    • A SortedList collection adds it in sequence by key value.

    For Hashtables and SortedLists, the following statements are equivalent:

    myCollection.Add("Name", "Elvina")
    myCollection("Name") = "Elvina"

The Remove method removes one element from an ArrayList, Hashtable, or SortedList collection, based on a method argument you supply. An ArrayList removes the first element with a value that matches the Remove argument. Hashtables and SortedLists remove the element with a key value that matches the Remove argument.

The RemoveAt method removes an element of an ArrayList or SortedList collection based on its numeric index. The RemoveRange method removes a range of elements from an ArrayList.

For a Queue collection, the Enqueue and Dequeue methods add and remove items. For a Stack collection, the Push and Pop methods do the same.

.NET Collection Properties

Method

Description

Array List

Hash table

Sorted List

Queue

Stack

Capacity

Gets or sets the number of elements the collection can contain.

X

X

Count

Gets the number of elements the collection actually contains.

X

X

X

X

X

IsFixedSize

Gets a value indicating whether the collection has a fixed size.

X

X

X

IsReadOnly

Gets a value indicating whether the collection is read-only.

X

X

X

X

X

Item

Gets or sets the element at the specified index or key.

X

X

X

Keys

Gets a collection of keys in the source collection.

X

X

Values

Gets a collection of values in the source collection.

X

X

For more information about any of these objects, their properties, or their methods, search the MSDN Web site (msdn.microsoft.com/library) for the term System.Collections.

Accessing Objects

In Visual Basic .NET, objects no longer have default properties. Instead, you must spell out the name of any property you want to use. Suppose, for example, your Web page contains the following Web Server Control:

<asp:label id="lblMessage" runat="server" />

You can’t assign a value to this control by coding a statement such as the following:

lblMessage = "Pounding the computer won't help."

The variable lblMessage doesn’t contain the label control directly; instead, it contains a pointer to the label control object. The preceding statement tries to replace that pointer, and because a string value can’t point to an object, it will produce a type mismatch error. Here’s the correct statement:

lblMessage.Text = "Pounding the computer won't help."

Occasionally, Visual Basic .NET will let you retrieve the value of an object without specifying a property name—not because some objects have default properties but because type conversion happens to return the value you want. Remembering the cases where this works is usually harder than coding the exact property name you want.

Visual Basic .NET (and, for that matter, ASP.NET) is perfectly capable of using Component Object Model (COM) objects, very much as classic ASP pages have done for years. Here’s an example:

Dim cnOrderDb As Object
cnOrderDb = Server.CreateObject("ADODB.Connection")

Note the absence of a Set command at the beginning of the second statement. Set commands are neither required nor supported in Visual Basic .NET.

There is, however, a catch. Classic ASP pages use a so-called threading model called Single Threaded Apartment (STA). This model states that among all objects in a given apartment (and the apartment in this case is the Web page) only one object can execute at any given time. If two or three objects are all ready to execute, the first must end before the second can start, and so forth.

ASP.NET pages use the Multiple Threaded Apartment (MTA) threading model. If two or more objects are ready to execute, ASP.NET starts executing all of them simultaneously. This capability improves overall performance, but it requires special features in the implementation of each object. Under STA, for example, an object never has to worry about another object taking exclusive control of a resource or updating information unexpectedly. Under MTA, every object has to take these precautions. Otherwise, that object or another object might fail or produce incorrect results.

Tip

Any COM objects that a programmer created in Visual Basic 6 use STA threading. Any ASP.NET page that uses one of these objects will require the AspCompat="True" attribute.

Fortunately, ASP.NET supports an operating mode that executes STA objects safely. To request this mode, simply code the AspCompat="True" attribute in a <%@Page> tag. Here’s an example:

<%@Page AspCompat="True" Language="VB"%>

Setting this attribute to True results in a slight performance penalty, so code it only if necessary.

Coding Logic Statements

Visual Basic .NET preserves support for all logic statements that worked in previous versions of Visual Basic. What a refreshing change! There are, however, only two such statements: If and Select. Here’s the general format of an If statement:

If [condition] Then
  [Your statements go here]
Else
  [Your statements go here]
End If

As always, the Else and its following statements are optional. In a change from previous versions, though, the End If terminator and the line ending after Then are required. The compiler will no longer accept statements such as

If txtAge.Text = "" Then lblAgeMsg.Text = "You must enter an age."

The If...ElseIf format is still supported as well, which is useful when you need to test a series of conditions until you find one that’s True. Here’s an example:

If strName = "Uang" Then
  strGift = "Bus"
ElseIf strName = "Uba" Then
  strGift = "Car"
ElseIf strName = "Uday" Then
  strGift = "Truck"
ElseIf strName = "Ugo" Then
  strGift = "Bus"
ElseIf strName = "Ujana" Then
  strGift = "Car"
End If

In such cases, the ElseIf form can be much easier than a more typical nesting of If...Else...End If statements.

The Case statement provides another way to test a series of conditions until one is true. The Case statement has this syntax:

Select Case [expression]
  Case [expression]
  Case [expression]
  Case Else
End Select

You can code as many Case statements as you like, and the Case Else statement is optional. Visual Basic .NET uses the Case expressions of Visual Basic 6, which are more flexible and powerful than those available in VBScript. The following statement, for example, is completely valid:

Select lngAge
  Case < 1
    lblDesc.Text = "Infant"
  Case 1 To 5
    lblDesc.Text = "Toddler"
  Case 6, 8
    lblDesc.Text = "Even Child"
  Case 7, 9
    lblDesc.Text = "Odd Child"
  Case 10 To 12
    lblDesc.Text = "Pre-teen"
  Case Else
    lblDesc.Text = "Trouble"
End Select

In the true spirit of progress, the following logical functions are obsolete. Visual Basic .NET no longer supports them. Goodbye.

IsEmpty, IsMissing, IsNull, IsObject

Visual Basic .NET does, however, support all the logical functions listed in the following table. Instead of using one of the stricken functions listed above, use IsDbNull for database fields and IsNothing for everything else.

Logical Functions in Visual Basic .NET

Result Type

Function

Description

Object

Choose

Selects and returns a value from a list of arguments.

Object

IIf

Returns one of two objects, depending on the evaluation of an expression.

Boolean

IsDbNull

Returns a Boolean value indicating whether an expression evaluates to the System.DBNull class.

Boolean

IsError

Returns a Boolean value indicating whether an expression is an error value.

Boolean

IsNothing

Returns a Boolean value indicating whether an expression has no object assigned to it.

Boolean

IsNumeric

Returns a Boolean value indicating whether Visual Basic .NET can convert an expression to a number.

Boolean

IsReference

Returns a Boolean value of True if the expression represents an Object variable that currently has no object assigned to it; otherwise, it returns False.

String

Partition

Returns a String indicating where a number occurs within a calculated series of ranges.

Object

Switch

Evaluates a list of expressions and returns a Variant value or an expression associated with the first expression in the list that’s True.

The Choose function expects to receive an index value followed by a series of expressions. If the index value is 1, Choose evaluates and returns the first expression. If the index is 2, Choose evaluates the second expression, and so forth. Here’s an example:

strVolunteer = Choose(intNum, "Pablo", "Quinta", "Radwan")

The IIf function returns one of two expressions depending on whether an expression is True or False. Here’s a case in point:

strSize = IIf(intWaist > 30, "Large", "Small")

The Partition function is a weird one. Here are its syntax and a typical statement:

Partition(Number, Start, Stop, Interval)
Partition(lngAge, 0, 99, 20)

When Visual Basic .NET evaluates this statement, it sets up a series of numeric ranges such as the following:

Range Name

Low Value

High Value

"0: 19"

0

19

"20: 39"

20

39

"40: 59"

40

59

"60: 79"

60

79

"80: 99"

80

99

The ranges start at the Start value and increase by Interval until they reach the Stop value. Visual Basic .NET then determines which range the given Number falls within and returns the name of that range as a string. For example, after Visual Basic .NET executes the following expression, strBracket will contain "20: 39".

strBracket = Partition(25, 0, 99, 20)

The Switch function interprets a list of paired expressions and values. If the first argument you pass to Switch is True, Switch evaluates and returns the second argument. If the third argument is true, Switch returns the fourth argument, and so forth. Here’s an example:

strCity = Switch(strEntree = "Kidney Pie", "London", _
                strEntree = "Wiener Schnitzel", "Munich", _
                strEntree = "Kielbasa", "Warsaw", _
                strEntree = "Chop Suey", "San Francisco")

If another part of your code set strEntree to "Wiener Schnitzel" (the third argument), this statement will assign the value "Munich" (the fourth argument) to the variable strCity, and so on.

Note

Each logical expression (that is, each odd-numbered argument) can differ completely from the rest. There’s no need for them all to test the same variable.

Writing Loops

Visual Basic .NET supports most of the same looping and logic constructs, itemized in the next table, that Visual Basic has supported for years. The GoTo and GoSub statements are notable omissions. Another change involves the While... Wend loop, which is now a While... End While loop.

Visual Basic .NET Loop Constructs

Syntax

Description

Do [{While | Until} condition]

  [Exit Do]
Loop

Executes a loop while or until the condition is True. Depending on condition, the loop might not execute at all.

Do
  [Exit Do]
Loop [{While | Until} condition]

Executes a loop while or until the condition is True. The loop will execute at least once.

For counter = start To end [Step step]
  [Exit For]
Next

Executes a loop once for each value in a series that begins with start, ends with end, and increments by step.

For Each element In group
  [Exit For]
Next

Executes a loop once for each element in a collection or array. During each iteration, the element variable points to a different element.

While expression
End While

Executes a loop while the condition is True. The Do While... Loop structure is equivalent.

Defining Subroutines, Functions, and Classes

Visual Basic .NET supports the same subroutine and function features as other versions of Visual Basic. For your reference, the required syntaxes appear here:

Sub name [(argument As type, ...)]
    [statements]
    [Exit Sub]
    [statements]
End Sub

Function name [(argument As type, ...)] As type
    [statements]
    [Exit Function]
    [statements]
    name = expression
    [statements]
    return expression
End Function

The difference between a Sub and a Function is that only a Function returns a value. You can set the return value of a Function in two different ways:

  • You can assign a value to the function name as if it were a variable:

    Function Whatever(astrName As String) As String
      [statements]
      Whatever = "This is the end."
    End Function
  • You can code a Return statement that includes an expression:

    Function Whatever(astrName As String) As String
      [statements]
      Return "This is the end."
    End Function

The choice of method is up to you, and it will probably depend on the structure of your code. The Return statement immediately exits the function, but assigning a value to the function name doesn’t. If you invoke a function without using the return value in an expression, Visual Basic .NET discards it. The following invocation, for example, discards the return value:

Whatever("Hazel")

When you call a subroutine, Visual Basic .NET requires parentheses around the arguments. Thus, the first of the following statements will produce a compiler error. The second statement is correct.

Response.Write "This will happen often."
Response.Write("This will happen often.")

By default, past versions of Visual Basic passed all subroutine and function arguments by reference (ByRef). This means the subroutine or function received a pointer to the actual argument.

By default, Visual Basic .NET subroutines and functions receive arguments by value (ByVal). Visual Basic .NET copies the value in the calling procedure and gives the subroutine or function the address of the copy. This operation has two consequences:

  • Copying each argument value consumes extra resources on the server.

  • If a subroutine or function modifies the value of an argument passed by value, the variable in the calling procedure remains unchanged.

To override the default and make a subroutine or function receive arguments by reference, code ByRef just before the argument name. Here’s an example:

Function Whatever(ByRef astrName As String) As String

Visual Basic .NET supports recursive subroutine and function calls, meaning that a subroutine or function can call itself any number of times. However, deeply nesting such calls can lead to stack or memory overflow. Don’t call a subroutine or function recursively more than a few times without exiting.

The syntax for defining a class has also changed. Here’s the new form:

Public Class name
[ Implements interfacename ]
  Public Property propertyname As type
    Get
      propertyname = InternalValue
    End Get
    Set
      InternalValue = propertyname
    End Set
  End Property

  Private Sub name [(argument, ...)]
    [statements]
  End Sub

  Public Function name [(argument, ...)]
    [statements]
  End Function
End Class

Note the Get...End Get and Set...End Set sequences within the property definition. These are both required unless you code ReadOnly or WriteOnly as follows:

Public ReadOnly Property Count As Long
Public WriteOnly Property Count As Long
  • If you code ReadOnly, other programs can retrieve the property value, but they can’t change it. A ReadOnly property must include a Get...End Get block, but can’t contain a Set...End Set block.

  • If you code WriteOnly, other programs can change the property value, but they can’t retrieve it. A WriteOnly property must include a Set...End Set block, but can’t contain a Get...End Get block.

In a Get procedure, you return a value to the calling procedure by assigning it to the property name. Here’s an example:

Public Property Height As Long
    Get
      Height = lngHeight
    End Get
  End Property

In a Set procedure, there are two different ways to retrieve the value that the calling procedure sent. If you coded arguments on the Set statement, you read those arguments as follows:

Set (alngHeight as long)
  mlngCurHeight = alngHeight
End Set

If you didn’t code arguments, then you read the implicit argument Value:

Set
  mlngCurHeight = Value
End Set

Although the examples in this chapter specify Public access, all the modifiers listed in the table below are available. In practice, most access modifiers are either Public (the property or method is accessible outside the current class) or Private (the property or method is accessible only within the current class). The default is Private.

Visual Basic .NET Access Modifiers

Access Modifier

Description

Public

The entity will be available to all other entities.

Private

The entity will be available only to entities within the context of its declaration, including any nested entities.

Protected

The entity will be available only within its own class or a derived class.

Friend

The entity will be available only within the program that contains its declaration.

Protected Friend

The entities will have the union of Protected and Friend accessibility.

Shadows

Indicates that this class shadows (that is, uses the same name as) an identically named programming element in a base class, making the element in the base class un-available.

MustInherit

Indicates that the class contains methods that a deriving class must implement.

NotInheritable

Indicates that no further inheritance of the current class is allowed.

interfacename

The name of the interface this class implements.

Handling Errors

Until now, if you didn’t want a serious error to terminate your Visual Basic code, the only alternative was to precede the risky statement with an On Error Resume Next statement. Doing so invoked an operating mode where serious errors updated an Err object rather than terminating the ASP.NET page, making it the Web developer’s responsibility to check the status of the Err object after each statement. To resume normal error checking, the developer coded On Error GoTo 0.

These facilities are still present in Visual Basic .NET, but so is a much better approach called structured exception handling. Using this approach involves coding the following structure:

Try
    [risky statements]
  Catch [optional filter]
    [statements]
  Catch [optional filter]
    [statements]
  ...
  Finally
    [statements]
End Try

Visual Basic .NET executes statements after the opening Try statement and before the first Catch statement normally, unless and until an error occurs. If an error does occur, Visual Basic .NET examines each Catch statement until it finds one with a condition that matches that error.

If a Catch statement contains a matching condition, control transfers to the first line of code in that Catch block. If no Catch statement contains a matching condition, the search proceeds to the Catch statements of any Try...End Try block that contains the block where the exception occurred.

This process continues until Visual Basic .NET finds a matching Catch block or no more Try...End Try blocks remain. If no blocks remain, the error asserts itself.

Visual Basic .NET always executes the code in the Finally section last, regardless of whether it executed any Catch block code. Code in this section usually closes files, releases objects, and performs other kinds of cleanup.

You can code Catch block filters in either of two ways. In the first, Visual Basic .NET filters errors based on the class of the exception. The following is an example.

Try
    ["Try" statements]
  Catch e as ClassLoadException
    [error handling statements]
  Finally
    [cleanup statements]
End Try

If a ClassLoadException occurs while Visual Basic .NET is executing a statement you coded between Try and the first Catch, Visual Basic .NET executes the code within the specified Catch block (and then the code in the Finally block). You can write as many of these Catch statements (and thereby catch as many different kinds of exceptions) as you want.

Knowing what exception classes to catch is less of a problem than you might suspect. In many cases, the reason you’re coding the Try block is that your Web page has already blown up for a condition you’d rather handle internally. In this case, you can copy the name of the exception class out of the error message and paste it into your code. Otherwise, the documentation for each object in the .NET Framework lists the types of exceptions that are possible.

The second way of coding Catch block filters is to code any conditional expression. One common use of this form of Catch filter is to test for specific error numbers, as shown in the following code:

Try
  y = 0
  x /= y
   Catch ex As Exception When y = 0
     x = 0
     lblError.Text = "Divide by zero"
  Finally
    [cleanup statements]
End Try

To catch any and all exceptions, code:

Catch ex as Exception

As you might have noticed, Catch statements receive an Exception object. Some exceptions return specialized objects, but most of them inherit the properties shown in the table below. The majority of exceptions use the generic Exception object and return exactly these properties. The Message property is generally the most useful.

.NET Exception Object Properties

Type

Name

Description

String

HelpLink

Gets or sets a link to the Help file associated with this exception.

Exception Object

InnerException

Gets a reference to the inner exception.

String

Message

Gets the error message text.

String

Source

Gets or sets a string containing the name of the application or the object that causes the error.

String

StackTrace

Gets the stack trace, which identifies the location in the code where the error occurs.

MethodBase Object

TargetSite

Gets the method that throws this exception.

If the need arises, you can also throw your own exceptions. The syntax is

Throw New System.Exception()

Note that this syntax creates a new Exception object and passes it as an argument. Inside the parentheses, you can specify

  • Nothing, to pass an exception with default properties.

  • A string value that contains an error message.

  • A string value and another exception object, which gives the next higher Catch handler your error message, as well as a reference to another error you detected.

Create a simple but bomb-proof calculator

The procedure that follows will develop a simple Web page that will add, subtract, multiply, or divide any two numbers the visitor types into a pair of text boxes. Of course, if the visitor enters a value that’s not a number, the calculation will fail. In this case, the Web page itself will display the error message rather than let ASP.NET display the system error message page. The graphic below shows this Web page in action:

Create a simple but bomb-proof calculator

Follow this procedure if you wish to create this Web page. If you’d rather look at the finished code, open the calc.aspx page in the ch05 folder of the sample files.

  1. Create a new, blank Web page containing an @ Page directive, then a code declaration block, then the usual HTML tags.

  2. Give the Web page a title by coding <title>Bomb-Proof Calculator</title> in the <head> section and <h1>Bomb-Proof Calculator</h1> just after the <body> tag. Insert any page formatting statements, such a links to style sheet files, that you like.

  3. Create a Web Form after the <h1></h1> heading. That is, add the following tags:

    <form runat="server">
    </form>
  4. Create three paragraphs between the <form> and </form> tags. To do this, add three lines, each containing <p></p>.

  5. Add two text boxes, named txtOp1 and txtOp2, to the first paragraph. The paragraph will then look like this:

    <p>
    <asp:TextBox id="txtOp1" runat="server" />
    <asp:TextBox id="txtOp2" runat="server" />
    </p>
  6. Add a drop-down list named ddlOper between the two text boxes. Make it offer choices of +, -, *, and /. Here’s the required code:

    <asp:DropDownList id="ddlOper" runat="server">
      <asp:ListItem>+</asp:ListItem>
      <asp:ListItem>-</asp:ListItem>
      <asp:ListItem>*</asp:ListItem>
      <asp:ListItem>/</asp:ListItem>
    </asp:DropDownList>
  7. Add an equal sign and a label control named lblResult after the second text box. Here’s the code:

    =
    <asp:label id="lblResult" runat="server" />
  8. Add a Submit button to the second paragraph. The following code will suffice. The <p> and </p> tags are some of those you entered in step 4.

    <p><asp:Button id="btnSub" Text="Submit" runat="server"/></p>
  9. Add a Label control named lblMessage to the third paragraph. Here’s how the paragraph should look when you’re finished:

    <p><asp:label id="lblMessage" runat="server" /></p>
  10. Save the Web page as calc.aspx and load it into your browser by means of an http:// URL. You should find that it resembles the previous figure but does nothing when you click Submit.

  11. Add a Page_Load subroutine to the code declaration block you created in step 1. This requires the following statements:

    Sub Page_Load(sender As Object, e As EventArgs)
    End Sub
  12. It would be pointless to perform a calculation the first time the Web page loads. The visitor, at that point, has had no opportunity to enter any numbers. Therefore, code an If statement that determines whether a postback is in effect. The Page_Load subroutine will then look like this:

    Sub Page_Load(sender As Object, e As EventArgs)
      If Page.IsPostBack Then
      End If
    End Sub
  13. Between the two statements you added in step 12, code a Select Case statement that performs the requested operation on the two numbers.

    Select Case ddlOper.SelectedItem.Text
      Case "+"
        lblResult.Text = Cdbl(txtOp1.Text) + _
                         Cdbl(txtOp2.Text)
      Case "-"
        lblResult.Text = Cdbl(txtOp1.Text) - _
                         Cdbl(txtOp2.Text)
      Case "*"
        lblResult.Text = Cdbl(txtOp1.Text) * _
                         Cdbl(txtOp2.Text)
      Case Else
        lblResult.Text = Cdbl(txtOp1.Text) / _
                         Cdbl(txtOp2.Text)
      End Select

    The expression ddlOper.SelectedItem.Text returns the text of the list box item that the visitor selects.

    The four Case statements differentiate among the four possible values.

    The statement following each Case statement converts the two text box values to Doubles, performs the requested calculation, and stores the result in the lblResult label object you created in step 7.

  14. If you save the Web page at this point and try performing calculations, you should find that all goes well as long as you enter two numeric operands. If you make an invalid entry, however, the page will fail and display an error page like the one shown here.

    Create a simple but bomb-proof calculator
  15. Add a Try statement before the Select statement you added in step 13 and an End Try statement after the End Select statement.

  16. After the End Select statement you added in step 13, add the Catch statement that appears in the following code.

    Try
    '   Select statement from step 13
      Catch ex as Exception
    End Try

    This Catch statement will catch all exceptions. If an exception occurs, the variable ex will point to a relevant exception object.

  17. After the Catch statement you added in the previous step, enter a statement that copies the current error message to the Label control you created in step 9. Visual Basic .NET will execute this statement only if an exception occurs.

      Catch ex as Exception
        lblMessage.Text = ex.Message
    End Try
  18. Add the following statement after the End Select statement that terminates the Select Case block. This will erase any error message the lblMessage label control might contain.

    lblMessage.Text = ""

    The presence of this statement also proves that if an exception occurs, the rest of the code in the Try block doesn’t execute. If the rest of the code in the Try block did execute, this statement would wipe out the error message.

  19. This completes the code for the calc.aspx page. Save the page and try running it again. You should no longer be able to bomb it by entering invalid values; the page will simply display an error message as shown in this graphic. The code listing for the entire page follows.

    Create a simple but bomb-proof calculator
    <%@Page Language="VB" Debug="True"%>
    <script runat="server">
    Sub Page_Load(sender As Object, e As EventArgs)
      If Page.IsPostBack Then
        Try
          Select Case ddlOper.SelectedItem.Text
            Case "+"
              lblResult.Text = Cdbl(txtOp1.Text) + _
                               Cdbl(txtOp2.Text)
            Case "-"
              lblResult.Text = Cdbl(txtOp1.Text) - _
                               Cdbl(txtOp2.Text)
            Case "*"
              lblResult.Text = Cdbl(txtOp1.Text) * _
                               Cdbl(txtOp2.Text)
            Case Else
              lblResult.Text = Cdbl(txtOp1.Text) / _
                               Cdbl(txtOp2.Text)
            End Select
          lblMessage.Text = ""
        Catch ex as Exception
          lblMessage.Text = ex.Message
        End Try
      End If
    End Sub
    </script>
    <html>
    <head>
    <title>Bomb-Proof Calculator</title>
    <link rel="stylesheet" type="text/css" href="../normal.css">
    </head>
    <body>
    <h1>Bomb-Proof Calculator</h1>
    <form runat="server">
    <p>
    <asp:TextBox id="txtOp1" runat="server" />
    <asp:DropDownList id="ddlOper" runat="server">
      <asp:ListItem>+</asp:ListItem>
      <asp:ListItem>-</asp:ListItem>
      <asp:ListItem>*</asp:ListItem>
      <asp:ListItem>/</asp:ListItem>
    </asp:DropDownList>
    <asp:TextBox id="txtOp2" runat="server" />
     =
     <asp:label id="lblResult" runat="server" />
    </p>
    <p><asp:Button id="btnSub" Text="Submit" runat="server"/></p>
    <p><asp:label id="lblMessage" runat="server" /></p>
    </form>
    </body>
    </html>

Summary

This chapter explained the basic structure of Visual Basic .NET by examining the syntax and capabilities of its literals, variables, statements, operators, functions, and other elements. Although Visual Basic .NET is an easy programming language to learn, it’s also a broad and comprehensive language suitable for complex projects.

The need for Visual Basic to operate with the common language runtime has imposed a variety of changes on the language. For the most part, these changes are worthwhile and modernizing, but they do require study, even for experienced Visual Basic programmers.

The next chapter will introduce a number of database concepts and terms you’ll need for developing database-driven Web sites.

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

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