Home > Articles


  • Print
  • + Share This

Functional Changes

In addition to the syntactical changes, VB .NET behaves differently from previous versions in several respects. This section details the most significant of those changes.


Several of the most obvious and productivity-enhancing changes in the language are related to dimensioning and instantiating variables.

As you might be aware through painful experience, in prior versions, a declaration like so

Dim x,y,z As Integer

did not result in three Integer variables. In fact, the first two variables were declared as Variant, which wastes memory and has the potential of causing type conversion problems down the road. In VB .NET, multiple declarations work as expected, and so the same declaration will result in three Integer variables. In addition, VB .NET supports the capability to use the declaration

Dim z

when the Option Strict statement is set to Off. In this case, rather than result in a Variant, the variable z is of type System.Object. Also note that unlike in previous versions, Option Explicit is defaulted to On so that variables cannot be used without first declaring them.

VB .NET also supports parameterized constructors so that objects can be initialized during the declaration. This, coupled with support for initialization during declaration, allows VB .NET to support the following types of syntax:

Dim dtAaron As New DateTime(1974, 4, 8)
Dim strName As String = "Hank Aaron"
Dim arTheropods() As String = {"Tyrannosaur", "Allosaurus", "Deinonychus"}

In this example, the dtAaron variable is declared as a DateTime structure and instantiated with arguments passed to the constructor specifying the day Hank Aaron hit his 715th homerun. This is shorthand for the statement:

Dim dtAaron As DateTime = New DateTime(1974, 4, 8)

In the second example, VB .NET takes care of calling the constructor for the String variable to allow developers to work with strings in a familiar fashion. The third example shows how to initialize an array of strings during declaration.


Although the constants you would expect (those prefixed with "vb") exist within the Microsoft.VisualBasic namespace, they also are exposed through enumerated types. Because the methods of the namespace expect the enumerated types, it is recommended that you use them rather than the constants.

Object Creation

Two other changes from the behavior of previous versions of VB are related to the creation of objects using the New operator. In previous versions the statement

Dim dino As New Dinosaur

would result in the compiler actually wrapping each line of code that referenced dino with a check to see whether the variable was Nothing. If so, the object was instantiated. In VB .NET, implicit object creation is not supported, and so the object is instantiated when the Dim statement is encountered. As a result, if you're going to use the New operator in a declaration, you'll want to place the declaration within the procedure in a place you know the variable will be used. In other words, it is more efficient if you defer dimensioning variables that might end up not being used, as long as possible.

In addition, in VB 6.0, the New operator actually used an internal algorithm that was more efficient to instantiate classes within the same project. In VB .NET, the CLR creates and manages all object instances, and so there is no difference when New is used with classes in the local assembly versus a remote assembly.

Finally, the CreateObject function, although still supported, will only be used to create a COM object. All managed classes are instantiated with the New keyword.


As shown in Table 3.2, VB .NET adds support for new operators. Perhaps the most significant from a keystroke-saving perspective are the operators that perform their operation and assign the result to the variable. For example, in VB 6.0, to concatenate a string on two lines, you would do the following:

Dim strMessage As String

strMessage = "This is a message that will be pretty long,"
strMessage = strMessage & " so I'll break it up a little."

In VB .NET, this can be compacted to the following:

strMessage = "This is a message that will be pretty long,"
strMessage &= " so I'll break it up a little."

In addition to concatenation, addition, subtraction, multiplication, division, and exponentiation are supported using this compacted syntax.

VB .NET also does not support default properties, and so the statement

Text1 = strName

does not assign the string variable strName to the Text property of the Text1 object. As a result, you must explicitly use the property. The good news is that this means the Set and Let statements, which caused a good deal of confusion, are no longer required or supported. The one exception to default properties is in the case where the property accepts a parameter. In this instance, you can mark the property as the default so that working with objects that support collections through properties such as Item is simplified.

Operators evaluation in expressions also can be short-circuited in VB .NET so that a procedure like the one that follows can be more efficient:

Sub Insert(ByVal value As Integer, ByVal sortedArr() As Integer)
  Dim intIndex, intIndxSrch As Integer
  Dim intArrCount As Integer = sortedArr.Length

  `Scan for entry less than one to be inserted
  While intIndxSrch < intArrCount AndAlso value > sortedArr(intIndxSrch)
    intIndxSrch += 1
  End While

  `Make room for new value --- move remaining items up
End Sub

In this example, the Insert procedure inserts a new value in a sorted array. Note that the While loop contains the new AndAlso operator with two expressions. Using short-circuit evaluation, the second condition, which is the more expensive of the two, will not be executed if the first condition returns False. In the past, you needed to place these conditions on separate lines to gain this efficiency. Short-circuiting also is implemented with the new OrElse operator when the first expression evaluates to True.


Although it was originally planned that the And, Or, Not, and Xor operators would only perform logical and not bitwise operations, feedback from the VB community ensured that these retain both functionalities and precedence rules as in VB 6.0.

Although not documented in VB 6.0, some developers became accustomed to using the VarPtr, VarPtrArray, VarPtrStringArray, ObjPtr, and StrPtr operators to return the memory addresses of variables of these data types. This was particularly useful when calling some Win32 API functions. These keywords are no longer supported in VB .NET.

Closely related to operators is the behavior of null values. In VB 6.0, null propagation was supported where adding or concatenating a value to Null, or a Variant that contained Null, always produced a null value. In VB .NET, Null has been replaced with Nothing, Variant with Object, and null propagation is not supported. As a result, the following behavior occurs in VB .NET when Option Strict is set to Off:

Dim x As Object
Dim i As Integer

i = 4
x = Nothing
i = i + x  ` i still equals 4

The Null keyword has been replaced with the System.DBNull class, and checking for nulls returned from databases can be done using the IsDBNull function. The equivalent syntax used in VB 6.0, where an empty string ("") concatenated to a null from a database produced an empty string, is still supported as well.

The absence of both variants and null values implies that functions that once accepted variants and possibly returned null values, such as Mid, Oct, Right, RTrim, Space, Str, Time, Trim, LTrim, UCase, and LCase, among others, now simply return their associated data types. As mentioned in Table 3.1, VB 6.0 also contained companion functions appended with $ (i.e. Trim$) that returned String values. These also have been replaced with overloaded methods that return a String.

Data Types

As discussed in Chapter 1, "The Microsoft .NET Architecture," all data types in VB .NET derive from System.Object and are therefore a part of the Common Type System (CTS) used by the CLR. VB .NET supports keywords that map to the CTS types shown in Table 1.1. This mapping is shown in Table 3.3.

Table 3.3  Data Type Mappings in VB .NET

VB .NET Data Type (with type character)

CTS Type





Char (new)


Decimal (@) (new)


Double (#)


Integer (%)


Long (&)


Short (new)


Single (!)


String ($)


As in VB 6.0, the type character can be used to automatically dimension a variable by appending it to the declaration. For example,

Dim z%

ensures that z is an Integer. However, because type characters make the code less readable, they are not recommended.

In addition, several of the data types include special characters (literal type characters) that can be used with literal values to force their representation to the appropriate type. These include C (Char), D (Decimal), R (Double), I (Integer), L (Long), S (Short), and F (Single). In other words, the statement

Dim b As Object

b = "T"C

forces the variable b to the type Char.

One of the most interesting aspects of Table 3.3, though, is the representation of integers. In VB 6.0, the Integer data type was 16 bits, and so the range was from -32,768 to 32,768. However, with the inclusion of Short to fill that spot, Integer is now a 32-bit value that is equivalent to the Long data type in VB 6.0. In turn, Long is now 64 bits with a range from ±9,223,372,036,854,775,808. Although this is desired because it brings VB .NET inline with other modern programming languages and applications, such as SQL Server, keep in mind that if you're porting existing code or rewriting code from VB 6.0 you'll want to change the data types as appropriate.

The internal representation of several data types in the CLR also is different from previous versions of VB. For example, the Boolean data type in VB 6.0 equated to -1 for True and 0 for False. Now, the more standard 0 for False and 1 for True is used by the runtime. However, to maintain backwards compatibility when working in VB .NET, the older -1 and 0 will be used. Keep in mind, though, that converting a Boolean to a CTS type such as System.Int32, or passing a Boolean to another managed language, will convert the result back to a 1 for True and 0 for False. Also, as mentioned in Table 3.3, the Date data type is no longer represented as a Double; it is mapped to System.DateTime, and implicit conversion between the two is no longer supported. Explicit conversion, however, can be accomplished by using the ToDouble and FromOADate methods of the DateTime class.

Of course, as should be obvious by now, the universal data type in previous versions of VB, the Variant, has been replaced with Object. The Object keyword used in VB 6.0 to refer to a late bound object has been subsumed into this definition.

Finally, as shown in Table 3.1 the Currency data type is no longer supported in VB .NET and has been replaced with the Decimal data type.


There are several important changes in VB .NET with regards to arrays. First, the lower bound of an array can no longer be set using the Option Base statement. As a result, the syntax

Dim s(0 to 10) As String

no longer is supported because all arrays are zero bound.


The designers of VB .NET originally planned that the array declaration would specify the number of elements and not the upper bound. In other words, the declaration

    Dim s(10) As String

would produce an array of 10 elements with indices from 0 through 9. However, this changed shortly before the beta 2 was released based on feedback from the VB community.

Also in VB .NET, by default, all arrays are variable-sized arrays, so they all can be resized using the ReDim statement. However, the ReDim statement cannot be used in place of the Dim statement to dimension an array as in VB 6.0.

In addition, as seen previously, an array can be populated in the declaration using the { } brackets like so:

Dim sosaHomers() As Short = {66, 63, 50, 64}

This syntax replaces the Array function formerly used to populate an array with arguments passed to the function. VB .NET still supports multidimensional arrays; however, the number of dimensions (referred to as the rank) must be set in the Dim statement. For example, the code

Dim arPlayers(,) As String
ReDim arPlayers(1, 3)

arPlayers(0, 0) = "Pitcher"
arPlayers(0, 1) = "Catcher"
arPlayers(0, 2) = "1B"
arPlayers(0, 3) = "2B"

arPlayers(1, 0) = "Roger Clemens"
arPlayers(1, 1) = "Mike Piazza"
arPlayers(1, 2) = "Mark McGwire"
arPlayers(1, 3) = "Eric Young"

works in VB .NET because the comma in the Dim statement denotes that there are two dimensions to the array. The same declaration without the comma works in VB 6.0. As in VB 6.0, VB .NET also allows you to change the upper bound of the last dimension in the array while preserving the contents of the array, and so the statement

ReDim Preserve arPlayers(1, 4)

immediately after the preceding code example successfully adds another element to the second dimension. The Preserve keyword ensures that the data is preserved.


As in VB 6.0, if you don't know the rank the array will have at development time, then dimension the array simply As Array or As Object.

VB .NET also still supports ragged arrays or arrays of arrays, which, like multidimensional arrays, allow you to store tabular type data but allow a varying number of elements. For example, the code in Listing 3.1 shows how you would create a ragged array by dimensioning the array As Object and then placing arrays inside it.

Listing 3.1  Creating Ragged Arrays in VB .NET. To create a ragged array use the Object type.

Dim a As Object
Dim b(0) As String
Dim c(1) As String
Dim obj As Object
Dim obj1 As Object

ReDim a(2)

` Fill the inner arrays
c(0) = "c1"
c(1) = "c2"
b(0) = "b1"

` Set the elements of the outer array
a(0) = b
a(1) = c
a(2) = "Third element"

` Traverse the contents of the array
For Each obj In a
    If IsArray(obj) Then
       For Each obj1 In obj
    End If

Note that Option Strict must be set to Off for this code to compile because late binding is occurring in the array referenced as a. Although this works in VB .NET, you might want to stick with multidimensional arrays because ragged arrays are not CLS compliant, and passing such an array to managed code written in another language might not work.

Many of these changes are made possible by the fact that all arrays in VB .NET are ultimately derived from System.Array. This class supports several shared methods that can be used to manipulate arrays as well as instance methods that can return data on a particular array. As you would expect, because System.Array is a reference type, assigning a variable to an existing array creates a reference to the array rather than a copy of it. To get a copy, you can use the Clone method of the Array class.


Shared methods can be called on a class without first instantiating an object from the class. This allows the class to contain various helper functions that can be used in a variety of situations. Conversely, instance methods are those that work on the current instance of the class.

For example, the declaration of the arPlayers array in VB .NET is actually translated to this:

Dim arPlayers As Array

arPlayers = Array.CreateInstance(GetType(String), 2, 4)

Note that the sizes of the dimensions as specified in the last two arguments to the CreateInstance method are set to 2 and 4, rather than 1 and 3 as you might expect. This is the case because arrays in the CLR typically are declared using the size of a dimension rather than the upper bound.

Even if the array is created in standard VB .NET syntax, all the Array methods and properties are available, the most important of which are shown in Table 3.4.

Table 3.4  Array Class Members




Shared method that searches a one-dimensional array for a specific element


Shared method that sets a range of the array to zero or Nothing


Shared method that copies a section of one array to another array


Shared method that initializes a new instance of the Array class


Shared method that returns the index of the first occurrence of a given value in a one-dimensional array


Shared method that returns the last index of the first occurrence of a given value in a one-dimensional array


Shared method that reverses the order of elements in a one-dimensional array


Shared method that sorts the elements of a one-dimensional array


Instance property that returns True if the array is fixed size


Instance property that returns whether the array is read-only


Instance property that returns whether access to the array is thread-safe


Instance property that returns the total number of elements in all dimensions of the array


Instance property that returns the number of dimensions


Instance property that returns an object that can be used to synchronize access to the array


Instance method that creates a copy of the array


Instance method that copies all or part of a one-dimensional array to another array


Instance method that returns the number of elements from a specified dimension of the array


Instance method that returns the lower bound of a specified dimension of the array


Instance method that returns the upper bound of a specified dimension of the array


Instance method that returns the specified values in the one-dimensional array


Instance method that sets the specified values in the one-dimensional array


Instance method that initializes every element of a value-type array if it has a constructor

To illustrate the use of the Array class, consider the procedure in Listing 3.2 used to find a specific item in an array.

Listing 3.2  Using the Array Class. This method exercises some of the functionality of the Array class to sort and search the array.

Function FindVal(ByVal value As Object, ByRef arr As Array) As Integer
  Dim intIndex As Integer

  If Not IsArray(Arr) Then
    Throw New ArgumentException( _
      "Argument is not an array or array has no elements")
    Return -1
  End If

    ` Sort the array
    ` Do a search
    intIndex = Array.BinarySearch(arr, value)
  Catch e As Exception
    Throw New Exception( _
      "There was an error working with the array: " & e.Message)
    Return -1
  End Try

  ` Negative if not found
  If intIndex < 0 Then
    Return -1
    Return intIndex
  End If

End Function

In this example, note that the FindVal procedure accepts an argument declared As Object to search for in the array, along with the array, and returns the index at which the value was found. The new IsArray function is used to determine whether the array has been initialized. If so, the array is first sorted using the Sort method and then a binary search is performed using BinarySearch. The return value from BinarySearch will be negative if the value is not found. Note that by definition, the BinarySearch method is case sensitive. In this case, the method returns the index of the element if the value is found, and a -1 if not. Since the array is passed to the method by reference, the array will be sorted when the method returns and the index will point to the new position of the value within the sorted array.


Many of the methods of the Array class work only with one-dimensional arrays. If you attempt to call these methods on multidimensional arrays, exceptions will be thrown. To work with, sort, and search multidimensional arrays, you'll need to employ your own techniques. Some of these can be found in Chapter 24 of my book Pure Visual Basic.

Alternatives to Arrays

Although arrays in VB .NET are easily mapped to the System.Array type, they are not always ideal for manipulating data within your application. To provide more choice and flexibility in working with collections of data, the Services Framework includes the System.Collections and System.Collections.Specialized namespaces. In fact, using these prebuilt collections can offload some of the array manipulation code you would normally write and can greatly improve performance—for example, when needing random access to an in-memory collection of data.

You can think of these namespaces as containing prebuilt data structures for handling data. For example, the System.Collections namespace contains the SortedList class that can be used to store a collection of values and associated keys. As the name implies, the data added to the collection is sorted automatically by the key, and the class contains various methods to access the data either by the key, index, or value. The following code illustrates the use of the SortedList class to store a collection of names:

Dim employees As New SortedList()
Dim i As Integer

employees.Add(3322, "Steve Lake")
employees.Add(6743, "Jody Davis")
employees.Add(1233, "George Mitterwald")
employees.Add(1341, "Tim Hosey")

For i = 0 To employees.Count - 1
  Console.WriteLine("{0}:{1}", _
    employees.GetByIndex(i).ToString, employees.GetKey(i).ToString)

When the For loop is executed, the names are printed in order by their key value.


Many of the collection classes include constructors that accept the initial capacity of the collection. Although the capacity of the collection is increased automatically as required through reallocation, this can be used to increase performance when you know ahead of time how many members the collection will contain. In the ArrayList and SortedList classes, the TrimToSize method can subsequently be called to minimize a lists memory overhead.

Although explicating all the classes and their members is beyond the scope of this book, the other types of collections, their descriptions, and uses can be seen in Table 3.5.

Table 3.5  Collection Classes in the System.Collections and System.Collections.Specialized Namespaces





Implements an array that is dynamically sized and able to be sorted

When you need to access the values by index


Manages a compact array of bit values represented as true (1) or false (0)

When you need to track a series of switches


Implements a collection of values and associated keys where the key is hashed

When you need to quickly access a value by the key for large collections


Implements a ListDictionary when the collection is small and dynamically switches to a HashTable as the collection grows for performance reasons



Implements a linked-list of key-value pairs

When you have fewer than 10 values and need access to them by the key


Implements a sorted collection of String keys and values

When you need access to the values by the hash code of the key or the index


Implements a first-in, first-out collection of objects

When you need to access the values in FIFO order


Implements a collection of key-value pairs sorted by the key

When you need to access the values in order by the key


Implements a last-in, first-out collection objects

When you need to access the values in LIFO order


Implements a collection of strings

-When you need to store strings and access them by index


Implements a hashtable where the key and value are both strings

When you need to access a large collection of strings by key

The only disadvantage to using most of the collection classes, except the last two shown in Table 3.5, is that they only accept keys and values of type Object. As a result, you'll need to convert the values to the appropriate type when retrieving them from the collection.


In VB 6.0, data could be grouped together in a user-defined type (UDT) using the Type statement. The UDT then could be instantiated and populated using dot notation and used as a return value from a function or as an argument to a procedure. Further, all the members of the type were public, and the type could only contain fields—no methods, properties, or events.

In VB .NET, the UDT has been replaced with the Structure. A Structure is much more powerful than a UDT. It can contain fields, methods, properties, events, enumerations, and even implement interfaces. In fact, a Structure can be thought of as simply a lightweight class. The primary difference is that a Structure is always a value type as discussed in Chapter 1, and is therefore always copied when used in an assignment statement or passed by value to a procedure. In addition, structures do not support inheritance, and you needn't use the New operator with structures because it is called implicitly in the declaration. However, structures can support constructors, as discussed in Chapter 4. As an example, consider the structure declaration shown in Listing 3.3.

Note that this structure encapsulates information about a baseball player. It contains public fields to represent the attributes of an offensive player—such as the number of hits (H), doubles (D), triples (T), homeruns (HR), and so on—as would be supported in a VB 6.0 Type. In addition, however, it contains public properties to expose the batting average (AVG) and slugging percentage (SLUG) along with a method to calculate the number of runs created (RunsCreated). Finally, the structure contains an enumerated type used to specify the player's position.

Listing 3.3  Player Structure in VB .NET. Note that it looks much like a class.

Structure Player
  Public Sub New(ByVal playerName As String)
    Name = playerName
  End Sub

  Public Enum pPosition
    C = 2
    P = 1
    First = 3
    Second = 4
    Third = 5
    Shortstop = 6
    Left = 7
    Center = 8
    Right = 9
  End Enum

  Public Name As String
  Public H As Integer
  Public D As Integer
  Public T As Integer
  Public HR As Integer
  Public BB As Integer
  Public AB As Integer
  Public SB As Integer
  Public Position As pPosition

  Public ReadOnly Property AVG() As Double
      Return H / AB
    End Get
  End Property

  Public ReadOnly Property SLUG() As Double
      Return (H + D + (2 * T) + (3 * HR)) / AB
    End Get
  End Property

  Public Function RunsCreated(ByVal useSB As Boolean) As Double
    If useSB Then
      Return ((H + BB) * (H + D + (2 * T) + (3 * HR) _
        + (0.7 * SB))) / (AB + BB)
      Return ((H + BB) * (H + D + (2 * T) + (3 * HR))) / (AB + BB)
    End If
  End Function

End Structure

A user of this structure might use the following code to represent the statistics from Sammy Sosa's 2000 season:

Dim sPlayer As Player

With sPlayer
    .Name = "Sammy Sosa"
    .AB = 604
    .H = 193
    .D = 38
    .T = 1
    .HR = 50
    .BB = 91
    .SB = 7
    .Position = Player.pPosition.Right
End With

Console.WriteLine(Math.Round(sPlayer.AVG, 3).ToString)
Console.WriteLine(Math.Round(sPlayer.SLUG, 3).ToString)
Console.WriteLine(Math.Round(sPlayer.RunsCreated(True), 1).ToString)

Because the structure contains a constructor (the New procedure), an alternate declaration would be

Dim sPlayer As New Player("Sammy Sosa")


As mentioned in Chapter 1, one of goals of the CLR is to provide a type-safe runtime environment. This means that by default, the CLR will enforce type-safety at compile time by not allowing an object of one type to be assigned to an object of a different type. This behavior is much different from VB 6.0, where type coercion happened implicitly, and VB developers didn't have to worry about statements like the following:

Dim s as String
s = 50

In this case, VB 6.0 implicitly converted the 50 to a string and made the assignment. In VB .NET, this same code will not compile unless the Option Strict statement is used and set to Off. This statement turns off the type-checking feature of the compiler, and then attempts to cast from one type to the other at runtime. In many instances, VB developers feel more comfortable turning off this option although it increases the likelihood of exceptions at runtime.

To perform explicit conversions, you can use the conversion functions (CStr, CBool, CDate, Cint, and so on), the CType and DirectCase functions, or methods of the System.Convert class. The CType function takes the expression to be converted and the type to convert to as parameters. For example, to convert the literal 50 to a string, you would use the following syntax:

s = CType(50, String)

The second argument can be used to explicitly pass a type, as in the preceding example, or you can use the GetType function to extract the type. You'll notice throughout the book that some listings have Option Strict set to Off for ease of coding and to make reading the code for VB developers more natural. The DirectCase function works in much the same way, although is more strict in that it only allows the conversion if the type parsed to it is exactly the same as the type being converted.

However, an easier approach is to use the System.Convert class, which contains seventeen To methods that convert to all of the system data types. In addition, each method supports myriads of overloads to convert from any of the types. Therefore, the previous code example could be rewritten:

s = Convert.ToString(50)

In addition, because all types are ultimately derived from System.Object, you can call the ToString method of any variable to convert it to a String. Calling ToString on a complex type, such as a structure or class, by default simply returns the type name as a string. However, if you define your own classes as described in Chapter 4, you can override the ToString method and return a string representation of your object.


Like arrays, strings in VB.NET are derived from a base class, in this case System.String, that contains both shared and instance members that allow you to manipulate the string. Table 3.6 shows the important members. Keep in mind that VB .NET also contains string functions in the Microsoft.VisualBasic.Strings module that wrap some of these methods or provide slightly altered functionality. Which technique you use is really a matter of personal preference. Existing VB developers will find the VB .NET functions more familiar, whereas developers new to the Microsoft product set, or coming from ASP, should use the Services Framework for the sake of uniformity among languages.

Table 3.6  String Class Members




Instance method that returns a new String with the same value


Shared method that compares two strings and returns an Integer specifying the result


Shared method that compares two strings and returns an Integer specifying the result without taking into account the language or culture


Instance method that compares this instance with a given object


Shared method that creates a new instance of a String with the same value as the specified string


Instance method that copies a portion of the string to a character array


Shared method that creates a new String from one or more strings or objects


Shared constant representing an empty string


Instance method that determines whether a given string matches the end of this string


Both a shared and instance method that determines whether two strings have the same value


Shared method used to format the string with the given format specification


Instance method that returns the index of the first occurrence of a string within this string


Instance method that inserts the given string at a given position within this string


Shared method that concatenates a given separator between each element in a given array


Instance method that returns the last occurrence of a given string within this string

PadLeft, PadRight

Instance methods that align the current string with spaces or a specified character for a specified length


Instance method that deletes the specified number of characters from this instance of the string at the specified location


Instance method that replaces all occurrences of a specified string with the given string


Instance method that splits the string into an array of strings based on a separator


Instance method that determines whether this string is prefixed with a given string


Instance method that retrieves a substring from the string


Instance method that copies the characters of the string to a character array

ToLower, ToUpper

Instance methods that return a copy of the string in lower- or uppercase

Trim, TrimEnd, TrimStart

Instance methods that remove spaces or a set of characters from the string

However, even though System.String is a reference type, the contents of a string are immutable, and all the methods that work on a string actually return a new instance of a string in the modified form. For example, to trim a string, the code

Dim s As String

s = "    Some spaces"
s = Trim(s)

actually results in a new string being created and assigned the same variable s. Immutability also affects assignment statements, and so the code

Dim s As String
Dim y As String

s = "Hello"
y = s
s = "New value"

does not change the value of y because y is actually a different string.

Because working with strings in this way can be inefficient for large strings, the Services Framework also contains the StringBuilder class in the System.Text namespace. This class can be used to build strings that can be directly modified perhaps by removing, replacing, or inserting characters, without creating a new string with each modification. For example, if you were to write code that read multiple text files and appended the text from each file to a string, it would be more efficient to use a StringBuilder so that the string could be modified directly, rather than creating a new string with each iteration of the loop. An analogous example is the following code:

Imports System.Text
Dim sbText As New StringBuilder()
Dim i As Integer


For i = 1 To 50

In this example, the StringBuilder object is instantiated, and its EnsureCapacity method is called to make sure that enough space can be allocated to hold the result. The loop then appends the text to the string. Remember that because the StringBuilder object is not actually a string, you need to use the ToString method to convert it to a string for other uses.


The StringBuilder class also is used to allocate string buffers that are filled by unmanaged DLL functions, as is frequently the case with the Win32 API.

VB .NET also does not support fixed-length strings, and so the code that would allocate a 30-character fixed-length string in VB 6.0

Dim s As String * 30

does not compile in VB.NET. The length of a string in VB .NET is determined by its contents only.

Because a string derives from a base class, you would think that you might be able to use a constructor for a string as in

Dim s As New String("E.D. Cope")

However, the String class does not support a constructor that accepts a string. An array of System.Char can be passed to the constructor like so:

Dim arrChar() As Char
arrChar = CType("O. Marsh", Char())
Dim strPaleo As New String(arrChar)

However, if you were going to do this, you would be better off using the initialization technique described earlier in the chapter because it would be more efficient. You would want to use the constructor when initializing a string with a repeated series of characters. The following code initializes a string to 50 spaces:

Dim s As New String(Convert.ToChar(" "), 50)

Finally, as shown in Table 3.6, the String class contains several versions of the Compare and Equals methods that you can use to perform both case-sensitive (the default) and case insensitive comparisons on strings. As in VB 6.0, string comparisons also can be done with the standard operators (=, <>, <, >, >=, <=) using either a binary or text comparison depending on the setting of Option Compare.

Block Scope

In previous versions of VB, variables could be declared at various scopes that included local (procedure), module, class, and global. Although VB .NET retains these scoping rules, it adds a lower level of scoping called the block level.

Block level scoping allows a developer to dimension a variable inside any block statement in VB .NET. These include looping constructs such as the For and While loops, If Then statements, and Try Catch statements, among others. If a variable is declared inside a block, the variables can be accessed only inside that block. For example, in the following code, the variable j is only accessible while in the If Then statement:

Dim i As Integer

If i = 3 Then
    Dim j As Integer
    j = 2
End If

j = 3 ` Causes a compiler error

In this case, the compiler stops you from referencing j outside the block. In addition, the compiler does not let you dimension a variable also called j with local scope. However, a j variable at the module or global level is allowed, although when executing the block, the block variable will be referenced, as you would expect.

Basically, the addition of block scope means that developers can more easily hide data and use it only where appropriate. It is good programming practice to declare variables at the lowest scope available and only raise them to a higher scope when absolutely necessary. This promotes reusability by creating fewer dependencies in your code.


Variables in block scope are not deallocated when the block is exited. Block-scoped variables live for the entirety of the procedure they are declared in. When entering the same block several times in the same invocation of the procedure, you might need to initialize the variable.


There are several subtle changes in the way VB .NET procedures and functions behave. The following list notes these changes:

  • Perhaps the most important is the change in the default parameter passing mechanism. In VB 6.0, if you did not specify how a parameter was to be passed, it was always passed by reference (ByRef). In VB .NET, this has changed to by-value (ByVal) because many developers didn't take the time to explicitly use the ByVal keyword. Passing parameters by-value protects them from changes inside the procedure, and therefore is safer.

  • TIP

    Although ByVal is now the default, you still should specify it explicitly for readability. In fact, VS .NET does this automatically.

  • In VB 6.0, if you passed the property of an object into a procedure using ByRef, the property was not changed as expected when the procedure ended. This has been corrected in VB .NET, where ByRef arguments work as expected with properties.

  • ParamArray parameters in VB 6.0 were always passed ByRef whereas in VB .NET they are passed ByVal, and the elements of the array must be declared as Object.

  • Arguments marked as Optional in VB 6.0 did not require a default value, whereas in VB .NET, default values are required. This requirement makes the IsMissing keyword obsolete, so it has been removed.

  • Returning data from functions also has changed in VB .NET with the inclusion of the Return keyword. This keyword can be used, rather than setting the return value equal to the name of the function. This makes the code both easier to read and write.

  • The way procedures can be called also has changed. In previous versions of VB, the capability to call a Sub procedure without using parentheses caused a good deal of confusion. In VB .NET, the Call keyword is retained although it is optional, but all procedures that accept arguments must be called with parentheses. If the procedure does not accept arguments, the parentheses are optional, although VS .NET includes them for you anyway. As a result the statement

  • MsgBox "Done with process", vbOK, "Dinosaurs"

    in VB.NET would now be

    MsgBox("Done with process", MsgBoxStyle.OKOnly, "Dinosaurs") 
  • At the procedure declaration level, new access modifiers can be used, covered in Chapter 4.

  • The GoSub statement is no longer supported. Although this has caused much discussion in the VB community, it is probably for the best because developers often can write code that is difficult to maintain with GoSub.

  • A procedure can no longer be marked as Static to automatically make all its local variables static (to retain their values between invocations of the procedure). Now, each variable that is to be static must be declared with the Static keyword.

Using the Compatibility Class

With the core language assembly, VB .NET ships with types that allow you to write code that is more compatible with VB 6.0. This includes classes, interfaces, structures, constants, and enumerated types that are used in VB 6.0.

Primarily, these include types that facilitate the communication between VB 6.0 controls, such as CheckBox and ListBox with classes in the Windows Forms namespace. In addition they include types that are useful for working with the ADO Data Control (ADOC) and implementing data binding. As a result they are not particularly interesting for devleopers of distributed applications.

That being the case, it is not recommended that you use these types in your applications.

  • + Share This
  • 🔖 Save To Your Account

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information

To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.


Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.


If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information

Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.


This site is not directed to children under the age of 13.


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information

If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information

Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents

California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure

Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact

Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice

We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020