Language Differences
With each new version of Visual Basic, Microsoft has expanded the language by offering new keywords, new syntactical elements, new conditional statements or modifiers, new attributes, and so on. Visual Basic .NET is no exception. It makes the same types of additions to the language as previous versions have, but on a much grander scale than before. Table 2-1 gives a complete list of keywords that have been added to the Visual Basic .NET language.
Visual Basic .NET Keyword | Description |
AddHandler and RemoveHandle | Dynamically adds or removes event handlers at runtime, respectively |
AndAlso and OrElse | Short circuited logical expressions that complement And and Or, respectively |
Ansi, Auto, and Unicode | Declare statement attributes |
CChar, CObj, CShort, CType, and DirectCast | Coercion functions |
Class, Interface, Module, and Structure | Type declaration statements |
Default | Attribute for indexed property declarations |
Delegate | Declare pointer to instance method or shared method |
GetType | Returns Type class for a given type |
Handles | Specifies event handled by a subroutine |
Imports | Includes given namespace in current code file |
Inherits | Optional statement used with a class to declare classes that inherit from another class |
MustInherit | Optional statement used with a class to declare the class as an abstract base class |
MustOverride | Optional subroutine attribute that specifies an inherited class must implement the subroutine |
MyBase | Refers to base class instance |
MyClass | Refers to the current class instance. Ignores a derived class. |
Namespace | Defines a namespace block |
NotInheritable | Optional statement used with Class to indicate the class cannot be inherited |
NotOverridable | Optional subroutine attribute which specifies that a subroutine cannot be overridden in a derived class |
Option Strict | Allows you to turn strict type conversion checking on or off. Default is off. |
Overloads | Optional subroutine attribute that indicates the subroutine overloads a subroutine with the same name, but different parameters |
Overridable | Optional subroutine attribute which specifies that a subroutine can be overridden in a derived class |
Overrides | Optional subroutine attribute that indicates the subroutine overrides a subroutine in the base class |
Protected | Class member attribute that limits member access to the class and any derived class |
Protected Friend | Same as Protected, but expands the scope to include access by any other class in the same assembly |
ReadOnly and WriteOnly | Attribute on a Property declaration to specify the property is read-only or write-only |
Return* | Statement used to return, possibly with a value from a subroutine |
Shadows | Attribute on class members to specify that a class member is distinct from a same-named base class member |
Short | 16-bit type known as Integer in Visual Basic 6 |
SyncLock | Specifies the start of a thread synchronization block |
Try, Catch, Finally, and When | Keywords related to structured error handling |
Throw | Keyword to throw an exception |
* Existing keyword with different behavior. |
Because the Upgrade Wizard generally does not modify or update your code to take advantage of new Visual Basic .NET features, only a subset of the new features come into play after an upgrade. Therefore, we will focus here on some of the general language differences that affect your upgraded Visual Basic 6 application. Chapter 11covers how to deal with these and other language changes in detail. The sections that follow describe the types of changes you will notice when you look at your upgraded Visual Basic .NET code.
All Subroutine Calls Must Have Parentheses
Parentheses are required on all subroutine calls. If you write code that does not use the Call keyword, as follows:
MsgBox "Hello World"
you are required to use parentheses in your Visual Basic .NET code, as follows:
MsgBox("Hello World")
ByVal or ByRef Is Required
In Visual Basic .NET, all subroutine parameters must be qualified with ByVal or ByRef. For example, instead of this Visual Basic 6 code:
Sub UpdateCustomerInfo(CustomerName As String) End Sub
you will see the following Visual Basic .NET code:
Sub UpdateCustomerInfo(ByRef CustomerName As String) End Sub
In this case, an unqualified Visual Basic 6 parameter has been upgraded to use the ByRef calling convention. In Visual Basic .NET, the default calling convention is ByRef.
Is That My Event?
Visual Basic 6 associates events by name, using the pattern <ObjectName>_<EventName>. For example, the click event associated with a command CommandButton is
Private Sub Command1_Click()
If you change the name of the Visual Basic 6 event to the name of a subroutine that does not match any other event, it becomes a simple subroutine. The name pattern, therefore, determines whether a subroutine is an event or not.
Handles Clause
Visual Basic .NET does not associate events by name. Instead, a subroutine is associated with an event if it includes the Handles clause. The name of the subroutine can be any name you want. The event that fires the subroutine is given in the Handles clause. For example, the click event associated with a Visual Basic .NET button has the following signature:
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click
Because the event hookup is an explicit part of the event declaration, you can use unique names for your events. For example, you can change the name of your Button1_Click event to YouClickedMyButton as follows:
Private Sub YouClickedMyButton(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles Button1.Click
Event Parameters
Another interesting change related to events is that event parameters are different between Visual Basic 6 and Visual Basic .NET. In Visual Basic 6, the event subroutine contains the name and type of each parameter. In Visual Basic .NET, the parameters are bundled up in an EventArgs object and passed in as a reference to that object. Also, the event subroutine for a Visual Basic .NET event includes a reference to the object that fired the event.
As an example of the different handling of event parameters in the two versions of Visual Basic, consider a form with a Listbox control on it, for which you need to write code to show the checked item.
In Visual Basic 6, you would write the following code:
Private Sub List1_ItemCheck(Item As Integer) MsgBox "You checked item: " & Item End Sub
The equivalent code in Visual Basic .NET is as follows:
Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, _ ByVal e As System.Windows.Forms.ItemCheckEventArgs) _ Handles CheckedListBox1.ItemCheck MsgBox("You checked item: " & e.Index) End Sub
Observe how the item that is checked is passed directly as a parameter in Visual Basic 6. In Visual Basic .NET, it is passed as a member of the passed-in ItemCheckEventArgs object e.
Arrays Must Have a Zero-Bound Lower Dimension
You cannot declare an array in Visual Basic .NET to have a nonzero-bound lower dimension. This requirement also means that you cannot use Option Base 1. In fact, you cannot specify a lower dimension in an array declaration, since it must always be zero. The following types of declarations are no longer supported:
Dim MyIntArray(-10 To 10) As Integer '21 elements Dim MyStringArray(1 To 100) As String '100 elements Option Base 1 Dim MyOptionBase1Array(5) As Long '5 elements (1-5)
Instead, you must use zero-based lower bound arrays, and you need to adjust the bounds to create an array with the same number of elements, such as
Dim MyIntArray(20) As Integer '21 elements (0-20) Dim MyStringArray(99) As String '100 elements (0-99) 'Option Base 1 'Not supported by VB .NET Dim MyOptionBase1Array(4) As Long '5 elements (0-4)
Refer to Chapter 11 for more information on how you can change your array declarations in Visual Basic .NET to be compatible with your array declarations in Visual Basic 6.
Fixed-Length Strings Are Not Supported
Visual Basic .NET does not support fixed-length strings. For example, the following type of declaration is not supported:
Dim MyString As String * 32
Instead, you can dimension the string as a fixed-length array of characters, as follows:
Dim MyString(32) As Char
Or you can use a special class, VBFixedLengthString, defined in the Visual Basic .NET compatibility library. If you use the VBFixedLengthString class the declaration will be:
Imports VB6 = Microsoft.VisualBasic.Compatibility.VB6 Dim MyFixedLenString As New VB6.FixedLengthString(32)
To set the value of a FixedLengthString variable you need to use the Value property as follows:
MyFixedLenString.Value = "This is my fixed length string"
Refer to Chapter 7 for more information about the Visual Basic .NET compatibility library.
Variant Data Type Is Eliminated
Visual Basic .NET eliminates the Variant data type. The main reason is that the underlying .NET Framework does not natively support the Variant type or anything like it. The closest approximation that the .NET Framework offers is the Object type. The Object type works somewhat like the Variant type because the Object type is the base type for all other types, such as Integer and String. Just as you can with a Variant, you can assign any type to an Object. However, in Visual Basic .NET, to get a strong type back out of a Variant to assign, for example, to an Integer or a String, you need to use a type-casting function, such as CInt or CString. With Visual Basic 6, you can write code such as the following:
Dim v As Variant Dim s As String v = "My variant contains a string" s = v
When using Visual Basic .NET, however, you need to use type conversion functions such as CStr, as follows:
Dim v As Variant Dim s As String v = "My variant contains a string" s = CStr(v)
Refer to Chapter 11 for more information on differences between the Visual Basic 6 Variant and Visual Basic .NET Object types.
Visibility of Variables Declared in Nested Scopes Is Limited
Variables that are declared in a nested scope, such as those occurring within an If Then or For Next block, are automatically moved to the beginning of the function. The Upgrade Wizard does this for compatibility reasons. In Visual Basic 6, a variable declared in any subscope is visible to the entire function. In Visual Basic .NET, this is not the case. A variable declared within a subscope is visible only within that subscope and any scope nested beneath it.
Take, for example, the following Visual Basic code:
Dim OuterScope As Long If OuterScope = False Then Dim InnerScope As Long End If InnerScope = 3
This code works fine in Visual Basic 6, but it will lead to a compiler error in Visual Basic .NET. The compiler error will occur on the last line, InnerScope = 3, and will indicate that the name InnerScope is not declared.
The Upgrade Wizard will upgrade your code so that no compiler error occurs. It does this by moving the declaration for InnerScope to the top of the function along with all other top-level declarations. Moving the variable declaration to the top-level scope allows the variable to be used from any scope within the function. This move makes the behavior compatible with Visual Basic 6. It is one of the few cases in which the Upgrade Wizard changes the order of code during upgrade. | |