If you have been a hardcore VB6 programmer and you've hesitated about switching to Visual Basic .NET, Visual Basic 2005 will change your mind and you'll want to take the leap forward to move to .NET.

The common complaint that people who have made this leap already often hear from programmers who are reluctant to move to VB .NET is that it is not VB-like, and moving to .NET means you have to unlearn many of the things you have painstakingly mastered in VB6.

Note that you cannot change the base index (of an array) of 0 to something else; the use of the To keyword is purely to enhance readability.

While the next release of Visual Basic will not allow you to bring back your VB6 days of glory, Microsoft knows the concerns VB6 programmers have and they've made a serious attempt in this new release to ease the learning curve. In this article, I will walk you through some of the new features in Visual Basic 2005 and I'll tell you how it will simplify your life as a developer.

New Keywords

Let's first talk about some language innovations and in particular, some new keywords in Visual Basic 2005.

Continue

The new Continue keyword allows you to skip an iteration in a loop. Consider the following snippet.

For i As Integer = 0 To 10
    ' prints out all odd 
    ' numbers from 0 to 10
    If i Mod 2 = 1 Then
MsgBox(i)
    Else
Continue For
    End If
Next

This code segment prints out all the odd numbers from 0 to 10. You can also use the Continue keyword in both a While loop and Do-While loop.

IsNot

Visual Basic includes a new comparison operator known as IsNot. Often you need to negate the comparison of an object, such as in this snippet.

Dim obj As Button
If Not obj Is Nothing Then
    ' obj contains an object reference
....
End If

In this case, your code would be more readable if you use the IsNot operator.

If obj IsNot Nothing Then
   ' obj contains an object reference
   ....
End If

To

Another new keyword in Visual Basic 2005 is the To keyword. The To keyword is used in an array declaration. Consider the following.

Dim numArray(50) As Integer

The above declaration may be mistaken by C, C#, C++, and Java programmers as declaring an integer array of 50 elements. In fact, in Visual Basic, it is actually 51 elements. The new To keyword will clarify this.

Dim numArray(0 to 50) As Integer

In this case, your code explicitly declares the array indices to be from 0 to 50 (51 elements in total). This will hopefully prevent confusion to programmers and aids readability.

Using

Often you need to create and use some resources and then immediately release the resources in order to conserve memory. Visual Basic 2005 comes with a new construct known as Using. The Using construct guarantees that the resources defined within the Using block will be disposed of after the execution of the block. Consider the following snippet.

Public Sub Data_Access( _
ByVal str As String)
Using conn As New SqlConnection(str)
Dim ds As DataSet
'---some code to perform data 
' access
End Using
...
...
End Sub

The conn and ds variables are only valid within the Using block. In fact, all variables declared within the block (ds, in this case) will be disposed after the Using block executes. The Using block is a good way for you to ensure that resources (especially COM objects and unmanaged code, which would not be unloaded automatically by the garbage collector in the CLR) are properly disposed of after they are no longer needed.

Operator Overloading

In Visual Basic 2005, you now not only can overload methods, you can also overload operators. Consider the MyString class (Listing 1).

Within this class you overload the “-” operator so that you can perform a minus operation on two MyString objects.

Dim s1 As New _
    MyString("Visual Basic .NET")
Dim s2 As New MyString("2005")
MsgBox(s1 - s2) 
' prints Visual Basic 2005

New Data Types

In Visual Basic 2005, you can now use the three new unsigned data types ? Unsigned Integer (UInteger), Unsigned Short (UShort), and Unsigned Long (ULong). The following shows some examples of the new unsigned data types.

Dim num1 As UInteger
' range: 0 to 4294967295
num1 = 4294967295

Dim num2 As UShort
' range: 0 to 65535
num2 = 65535

My Namespace

One of the shocks that VB6 programmers encountered when they migrate to Visual Basic .NET is the sheer number of class libraries available. VB6 programmers often struggle with finding the right class for the right task, and to them this task can be like finding a needle in a haystack.

Note that in Visual Basic 2005, at most one partial class need not have the Partial keyword.

To ease the pain of VB6 programmers, Microsoft has added the new My namespace in Visual Basic 2005.

The My namespace:

  • Provides shortcuts to commonly used functionality within the .NET Framework
  • Adds functionality that was previously difficult to find, difficult to use, or was simply not possible without unmanaged API calls

My includes the following objects (Figure 1).

Figure 1: The objects in the My namespace.
Figure 1: The objects in the My namespace.
  • Application
  • Computer
  • Forms
  • Resources
  • Settings
  • User
  • WebServices

For example, to get the computer to play a system sound, you can directly use the My.Computer object.

My.Computer.Audio.PlaySystemSound( _
   SystemSounds.Exclamation)

Contrast this to using the Win32 API to play audio, or using the Audio class within the Microsoft.VisualBasic.Devices namespace. (Who would have thought that this library was located in this namespace?)

Dim audio As New _
 Microsoft.VisualBasic.Devices.Audio()
audio.PlaySystemSound( _
   SystemSounds.Exclamation)

Another example of using the My namespace is downloading files from the Internet. The following statement downloads an image from the Web and then saves it onto your local drive:

My.Computer.Network.DownloadFile( _
   "<a href="http://www.code-magazine.com/";>http://www.code-magazine.com/<;/a>
   images/code_logo_white.gif", _
   "C:\Images\log.gif")

Partial Classes

In Visual Basic 2005, you can now split the definition of a class into multiple physical files using the new Partial keyword.

For example, you could rewrite the MyString class illustrated earlier as two separate partial classes (Listing 2).

Using partial classes you can now try to separate a class definition into multiple files, perhaps one class for containing all the properties definitions and another class for all the methods. To the compiler, the partial classes are treated as one single class.

Partial classes are useful for separating designer-generated code and business logic. For example, in Visual Studio .NET 2003, the designer-generated code for a Windows Form is embedded within the code-behind for the form. This often creates a mess when developers unknowingly modify the generated code. In Visual Studio 2005, the designer-generated code for WinForms are all saved in a separate partial class (Figure 2), so your code behind for your Windows form is now clear of all the clutter (Figure 3).

Figure 2: The designer generated code of a Windows Form saved in a separate file.
Figure 2: The designer generated code of a Windows Form saved in a separate file.
Figure 3: The code behind of a Windows Form.
Figure 3: The code behind of a Windows Form.

Apart from using partial classes to separate business logic from UI, you can also use partial classes to add extra methods to classes that are auto generated, e.g., a typed dataset. You can then regenerate the auto generated part of the file without breaking the extra methods.

Generics

Generics is a new feature in the .NET 2.0 Framework. As such, languages such as C# and Visual Basic 2005 now support this new feature.

You should use “Option Strict On” for design-time checking in Visual Studio 2005. This will ensure that the editor will flag an error when you try to use a data type that is not permitted on a constructed type.

Using Generics, you can define a class definition without fixing the data type that it is using at design time. To better understand how Generics work, consider the case of a Queue class. A queue is a first-in-first-out data structure and is useful for storing messages in the order they were received for sequential processing.

Lising 3 shows that the MyQueue class defines a circular queue data structure that allows items to be enqueued (inserted) and dequeued (removed).

What is notable in this class is that I have not fixed the specific data type of the items that can be inserted into the queue. Rather, I have used the Of keyword as a placeholder for the actual data type to be used.

Public Class MyQueue(Of itemType)

To use the MyQueue class with Integer values, simply instantiate the MyQueue class with “Of Integer” (in this case, q1 is known as a constructed type).

Dim q1 As New MyQueue(Of Integer)(3)
q1.Enqueue(5)
q1.Enqueue(6)
q1.Enqueue(7)
MsgBox(q1.Dequeue) ' prints 5
MsgBox(q1.Dequeue) ' prints 6
MsgBox(q1.Dequeue) ' prints 7
q1.Enqueue("A string") ' error

If you want to use the MyQueue class with string values, then use “Of String”.

Dim q2 As New MyQueue(Of String)(3)
q2.Enqueue("Microsoft ")
q2.Enqueue("VB 2005 ")
q2.Enqueue("rocks!")
MsgBox(q2.Dequeue) 'prints "Microsoft"
MsgBox(q2.Dequeue) 'prints "VB 2005 "
MsgBox(q2.Dequeue) 'prints "rocks!"
q2.Enqueue(5) ' error

The advantage of using generics for this example is that I do not need separate classes for different types of data types. Of course, one way would be to use an Object data type for the items inserted into the queue and during runtime perform type casting to get the required data type. However, doing so will result in late binding and will affect performance and type-safety.

To summarize, generics affords the following:

  • Type Safety. Generic types enforce type compliance at compile-time, and not run-time (as in the case of using Object). This reduces the chances of data-type conflict during run time.
  • Performance. The data types to be used in a Generic class are determined at compile time, hence there is no need to perform type casting during run time, which is a computationally costly process.
  • Code Reuse. Since you only need to write the class once and customize it to use with the various data types, there is a substantial amount of code-reuse.

Code Snippets

In an attempt to make Visual Basic more accessible to a wider developer base, Microsoft has made a very innovative addition to Visual Studio 2005 ? code snippets.

Code snippets are small, commonly-used blocks of code. Code snippets allow you to insert commonly-used code blocks into your project, thereby improving the efficiency of your development process. This is very useful for developers who are new to the language and need a way to jumpstart their development.

In the final release of Visual Studio 2005, it is expected that Microsoft will ship more than 500 code snippets, but in the current release (Beta 1 at the time of writing) there are only about 30 or so code snippets.

To insert a code snippet into your code, simply right-click in Code View and select Insert Snippet… (Figure 4).

Figure 4: Inserting code snippets.
Figure 4: Inserting code snippets.

You can then choose the code category that suits your purpose. For example, if you choose Security, you will see a listing like that shown in Figure 5.

Figure 5: Inserting a code snippet to encrypt a string.
Figure 5: Inserting a code snippet to encrypt a string.

If you choose Decrypt a String, a block of code would then be inserted into your application. To customize the code, simply replace the placeholder highlighted in yellow (Figure 6).

Figure 6: The inserted code snippet with the placeholder.
Figure 6: The inserted code snippet with the placeholder.

Code snippets are stored in the C:\Program Files\Microsoft Visual Studio 8\Vb\Snippets\1033 folder. They are stored as XML files so you can write your own code snippets to be shared among your colleagues.

XML Code Commenting

Another new features that is coming in Visual Basic 2005 is XML code commenting. XML code commenting was long supported in languages like C# and Java, and it is finally supported in this new release of Visual Basic.

XML code commenting allows you to use XML elements to document your code. To insert an XML comment, simply type three apostrophes before a class or method definition and the XML code templates will automatically be inserted for you (Figure 7).

Figure 7: The inserted XML comments.
Figure 7: The inserted XML comments.

There is a list of XML documentation tags that you can use to document your code. This list is available from MSDN at: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfTagsForDocumentationComments.asp.

Once you have documented your code with XML elements, an XML document containing all the comments in your code would be generated when you build your application. This XML document could then be processed by a third-party tool so that a help file may be generated. NDoc (http://ndoc.sourceforge.net/) is one such tool that helps to generate documentations for .NET assemblies. For a detailed look at how to use NDoc to generate professional-looking documentation, checkout my article, “Generating Documentation for Your Visual Basic .NET Applications” on MSDN at: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbgeneratingdocs.asp.

Editor Improvements

Besides the language innovations, the code editor in Visual Studio 2005 is also significantly improved to simplify Visual Basic development.

Autocorrect

In Visual Studio .NET 2003, if a statement contains an error, the offending keyword within that statement would be highlighted, together with the reason for the error. In Visual Studio 2005, Microsoft has gone one step further with the Autocorrect feature.

The Autocorrect feature tries to analyze the cause of the error and make suggestions. For example, you may have remembered to add a reference to the System.Data.dll for ADO.NET data access in your project, but have forgotten to import the System.Data namespace. In this case, if you try to declare a SqlDataReader variable, Visual Basic will flag the SqlDataReader class as not defined. Using Autocorrect, you can place your cursor over the underline and click the exclamation icon in red to view a list of suggested remedies (Figure 8).

Figure 8: Using Autocorrect to suggest remedies for an error.
Figure 8: Using Autocorrect to suggest remedies for an error.

In this case, you can either use a fully qualified name for the SqlDataReader class, or simply add an imports statement at the top of the code.

Exception Assistant

Another improvement in Visual Studio is the new Exception Assistant. The Exception Assistant will kick into action when a runtime error occurs. For example, in Figure 9 I have forgotten to add the New keyword to the instantiation statement, and using the Button object without instantiation will cause a runtime error. While this is a common error, it may take a Visual Studio .NET beginner a while to figure it out. The Exception Assistant tries to suggest ways to remedy the runtime error.

Figure 9: The Exception Assistant in action.
Figure 9: The Exception Assistant in action.

Listing 1: MyString class

Public Class MyString
    Private _text As String

    Public Sub New _
       (ByVal text As String)
_text = text
    End Sub

    Property Text() As String
Get
    Return _text
End Get
Set(ByVal value As String)
    _text = value
End Set
    End Property

    Public Shared Operator -( _
    ByVal str1 As MyString, _
    ByVal str2 As MyString) _
    As String
Return str1.Text.Substring _
   (0, str1.Text.Length - _
   str2.Text.Length) &amp; _
   str2.Text
    End Operator
End Class

Listing 2: Rewriting the MyString class as two partial classes

' saved in MyString1.vb
Public Class MyString
    Private _text As String

    Public Sub New _
       (ByVal text As String)
_text = text
    End Sub
    Property Text() As String
Get
    Return _text
End Get
Set(ByVal value As String)
    _text = value
End Set
    End Property
End Class

' saved in MyString2.vb
Partial Public Class MyString
    Public Shared Operator -( _
    ByVal str1 As MyString, _
    ByVal str2 As MyString) _
    As String
Return str1.Text.Substring _
   (0, str1.Text.Length - _
   str2.Text.Length) &amp; _
   str2.Text
    End Operator
End Class

Listing 3: MyQueue demonstrates Generics

Public Class MyQueue(Of itemType)
    Private element() As itemType
    Private _frontofQueue As Integer
    Private _backofQueue As Integer
    Private Queueisfull As Boolean = _
       False

    Public Sub New(ByVal size As _
       Integer)
ReDim element(size - 1)
_frontofQueue = 0
_backofQueue = 0
    End Sub

    Public Sub Enqueue( _
       ByVal item As itemType)
If QueueisFull Then
    Throw New Exception( _
       "Queue is full.")
End If
element(_backofQueue) = item
_backofQueue += 1
If _backofQueue &gt; _
    UBound(element) _
   Then _backofQueue = 0
If _backofQueue = _
    _frontofQueue _
   Then QueueisFull = True
    End Sub

    Public Function Dequeue() _
       As itemType
Dim item As itemType
If (_frontofQueue = _
   _backofQueue) _
   And Not Queueisfull Then
    Throw New Exception( _
       "Queue is empty.")
Else
    item = _
       element(_frontofQueue)
    _frontofQueue += 1
    If _frontofQueue &gt; _
       UBound(element) _
       Then _frontofQueue = 0
    Queueisfull = False
    Return item
End If
    End Function
End Class