Visual Basic .NET


The latest version of Visual Basic is a major leap forward in terms of functionality, with several features added to take advantage of the Common Language Specification ( CLS ) and the CLR.

Each generation of a language brings improvements. To understand why Visual Basic .NET implements the changes it does, consider for a moment some of the problems associated with previous versions of Visual Basic:

  • The Visual Basic runtime libraries :These are relatively large DLLs incorporating the base functionality, and are required for all Visual Basic programs to run. Common complaints concerned the size of these DLLs, and versioning problems (different libraries for different versions of VB). You might think that these have just been replaced by the CLR, but the CLR is much more than this, and addresses far more than just VB. While size may still be considered an issue, the redistributable CLR is around 18 MB and supports multiple versions.

  • Poor object-oriented features :Object-oriented programming gurus criticized Visual Basic for its lack of 'proper' functionality “ not providing features such as inheritance, overloading, and so on. Although these are valid points, many of the problems really stemmed from the capabilities of COM rather than Visual Basic itself.

  • Inability to create multi-threaded applications :With the introduction of Microsoft Transaction Server ( MTS ), n- tier architecture became a reality, and Visual Basic programmers started to get to grips with componentization. However, Visual Basic components were forced into an Apartment Threading model, a limitation that attracted much criticism from programmers who wanted to build multi-threaded components . Personally, I think much of this condemnation is misplaced, as I wonder how many people could actually write a fully threaded component (I'm not sure I could). Think about it “ managing the threads, state, and so on, isn't easy.

All of these problems disappear in Visual Basic .NET. The runtime libraries are no longer needed because they're taken care of by the CLR, and the object-oriented features have been massively improved (partly because of CLR and CLS support) and the whole threading issue has gone away. With the CLR, you just don't need to think about threading (unless you want to). Let's look at some of the new features in Visual Basic .NET.

Object-Oriented Features

The OO features were probably one of the enhancements most requested by programmers. I remember being at a Microsoft event when Visual Basic 6 was in beta, and the most frequently asked question was whether inheritance will be supported. Since this is an intrinsic feature of the CLR, it is now supported, and classes are inheritable by default. In fact, since everything in .NET is class based, you have an enormous amount of flexibility, as you can not only extend and overload your own classes, but many system ones too.

Classes

As in previous versions of Visual Basic, classes are created using the Class statement. However, the syntax has changed a little:

  [ Public  Private  Protected  Friend  Protected Friend ]   [Shadows]   [MustInherit  NotInheritable] Class className     End Class  
Note

Visual Basic still requires the underscore ( _ ) for line continuation “ to make things clearer, it's not shown in the preceding syntax outline.

Let's look at the keywords in more detail:

Keyword

Description

Public

The class is publicly accessible.

Private

The class can only be accessed within the file in which it is declared.

Protected

The class is only accessible from the containing class or types derived from the containing class.

Friend

The class is only accessible from this assembly.

Protected Friend

The class is only accessible from this program or types derived from the containing class.

Shadows

The class shadows an identically named class in a base class. Shadows is only available inside classes, structures, and interfaces.

MustInherit

This class is an abstract class, and the class members must be implemented by inheriting classes.

NotInheritable

This class is not inheritable.

Within a class, the member definition follows the same rules. Members that are not explicitly declared with a keyword are Public by default.

For example:

  Public Class Calculator     ' implementation goes here     End Class  

Or:

  Protected MustInherit Class Calculator     ' abstract implementation goes here     End Class  

Methods

Methods are declared as a Sub or a Function , but there are improvements to fit in with the inheritance rules. The syntax for a Sub is now:

  [Overloads  Overrides  Overridable  NotOverridable  MustOverride     Shadows  Shared]     [Private  Public  Protected  Friend  Protected Friend]     Sub subName [(parameters)]     End Sub  

The syntax for a Function is:

  [Overloads  Overrides  Overridable  NotOverridable  MustOverride     Shadows  Shared]     [Private  Public  Protected  Friend  Protected Friend]     Function  functionName  [(parameters)] [As  type  ]     End Function  

The various keywords are described in the following table:

Keyword

Description

Overloads

The member is overloaded, with more than one declaration existing, each with different parameters. Overloads is not required when overloading methods in the same class, but if it is used, it must be used on all overloaded methods.

Overrides

The member overrides an identically named member from a base class. This is useful for sub-classing situations where you want to provide your own implementation of a particular member. The overridden method must have the same signature; that is, the parameters and data types must match those of the base class member.

NotOverridable

The member cannot be overridden in a derived class.

Overridable

The method can be overridden by a derived class.

MustOverride

The member must be overridden in a derived class. This implies Overridable .

Shadows

The method shadows a method in a parent class. This means that the method in the parent class is not available, and allows creation of methods with a different signature (parameters & data types) than that of the parent. It effectively re-declares the type.

Shared

The member is shared by all instances of the class, and it exists independently of a class instance. This is equivalent to a static method in C# or C++.

Public

The member is publicly accessible.

Private

The member is only accessible within the class.

Protected

The member is only accessible from the containing class or types derived from the containing class.

Friend

The member is only accessible from this program.

Protected Friend

The member is only accessible from this program or types derived from the containing member.

For example:

  Public Class Calculator   Public Function Add(Op1 As Double, Op2 As Double) As Double   Return Op1 + Op2   End Function   End Class  
Note

This is an important change from previous function syntax “ the value of the function is now returned using the Return keyword, rather than by setting the function name to the value.

Properties

Properties can be implemented as Public member variables or by using the Property statement. For example:

 Public Class Calculator  Public Op1 As Double   Public Op2 As Double  Public Function Add() As Double       Return Op1 + Op2    End Function      End Class 

The class could be used in the following way:

  Dim calc As New Calculator   calc.Op1 = 123   calc.Op2 = 456   Response.Write(calc.Add())  

The preceding example uses public variables. The alternative (and preferred) approach is to use Property , the syntax of which has changed as follows:

  [Default  ReadOnly  WriteOnly] Property propertyName ([parameters])   [As type]   Get   ' code for getting the property   End Get     Set   ' code for setting the property   End Set     End Property  

A property defined as ReadOnly can only have the Get block. Likewise, a property with only a Get block must be marked as ReadOnly . The same applies for WriteOnly and the Set block. There is also no longer a Let option, as Set provides the same functionality.

For example:

 Public Class Calculator  Private _op1 As Double   Private _op2 As Double     Public Property Operand1() As Double   Get   Operand1 = _op1   End Get   Set   _op1 = value   End Set   End Property     Public Property Operand2() As Double   Get   Operand2 = _op2   End Get   Set   _op2 = value   End Set   End Property     End Class  

Notice the use of the keyword value in the Set block. This is the actual code you should type, as value is an implicit variable that contains the value of the property being set.

Default Properties and Property Parameters

Default properties are another area of change, as they are only supported on properties with a parameter list. Therefore, you could add a property called Result to your Calculator class, to contain the last result of an operation, but you wouldn't be able to make it the Default property. Hence, you can't code it like this:

  Default Property Result() As Double  

This stops you doing the following:

  Label1.Text = MyCalc  

To declare a default property, you need to have parameters (and these cannot be declared as ByRef ). For more details, consult the Visual Basic .NET documentation supplied with the .NET SDK.

Constructors and Object Creation

The Class_Initialize event has been removed from classes, but has been replaced with a member function called New , which enables you to inherit from constructors.

One of the cool new features of Visual Basic .NET is the use of overloading, which is perfect for providing constructors. The New() method is a special case for overloading, since the Overloads keyword is not required. For example, consider a Person class:

  Public Class Person     Private _firstName As String   Private _lastName  As String     Sub New()   _firstName = """"   _lastName = """"   End Sub     Sub New(firstName As String, lastName As String)   _firstName = firstName   _lastName = lastName   End Sub     Public Property FirstName() As String   ' property code here   End Property     Public Property LastName() As String   ' property code here   End Property     End Class  

In this example there are two occurrences of Sub New() : one without parameters, and another with . This means you can write:

  Dim coolDude As New Person()   coolDude.FirstName = "Vince"   coolDude.LastName = "Patel"  

Or

  Dim coolDude As New Person("Vince", "Patel")  

This provides a richer way of using classes and simplifies code.

Destructors and Object Destruction

Like the Class_Initialize() method, Class_Terminate() has also been replaced by a Destruct() method. For example:

  Sub Destruct()     ' code to clean up here     End Sub  

There has been a big change in the way destructors are called from previous versions of Visual Basic, and it revolves around the CLR. One of the good features of the CLR is garbage collection (GC) , which runs in the background collecting unused object references, freeing you from having to ensure that you always destroy them. However, the downside is that since it's a background task, you don't know exactly when your destructor is called.

During the time of the beta releases, there was a wide discussion regarding this, resulting in an extensive paper from Microsoft about garbage collection and its effects (search the MSDN Web site for Deterministic Finalization for more details). Some people were concerned that there might be cases where they would need to guarantee something happening (such as resource cleanup) when the object is no longer in use. If this is the case, then the advice is to create a method to house this functionality, and call this method when you have finished with the class instance.

In reality, the time difference between releasing the object instance, and it being garbage collected, is likely to be very small, since the garbage collector is always running.

Inheritance

As mentioned in the previous chapter, everything in .NET is an object, so you can inherit from pretty much anything. Consider the Person class as a base class; you could create a new class from it in the following way:

  Public Class Programmer   Inherits Person     Private _avgHoursSleepPerNight As Integer     Public Sub New()   MyBase.New()   End Sub   Public Sub New(firstName As String, lastName As String)   MyBase.New(firstName, lastName)   End Sub     Public Sub New(firstName As String, lastName As String, _   hoursSleep As Integer)   MyBase.New(firstName, lastName)   _avgHoursSleepPerNight = hoursSleep   End Sub     Public Property AvgHoursSleepPerNight() As Integer   Get   AvgHoursSleepPerNight = _avgHoursSleepPerNight   End Get   Set   _avgHoursSleepPerNight = value   End Set   End Property     End Class  

This class extends the existing Person class and adds a new property. Let's look at the way it does this.

First, after the class declarations comes the Inherits statement, where the base class we are inheriting from is specified:

 Public Class Programmer Inherits Person 

Next , come the definitions for the existing constructors. Our class provides an extra one, so we need to overload the base class constructors. Notice how the definitions of these match the definitions in the base class, and how we call the constructor of the base class using MyBase . We are not changing the existing constructors, just adding our own, so we just want to map functionality to the base class:

 Public Sub New()    MyBase.New() End Sub Public Sub New(firstName As String, lastName As String)    MyBase.New(firstName, lastName) End Sub 

Now we can add our extra constructor, which calls one of the previous constructors and then sets the additional property:

 Public Sub New(firstName As String, lastName As String, _                                     hoursSleep As Integer)    MyBase.New(firstName, lastName)    _avgHoursSleepPerNight = hoursSleep End Sub 

Finally, we add the definition of the new property:

 Public Property AvgHoursSleepPerNight() As Integer    Get       AvgHoursSleepPerNight = _avgHoursSleepPerNight    End Get    Set       _avgHoursSleepPerNight = value    End Set End Property 

In object-oriented terms, this is standard stuff, but it's new for Visual Basic and provides a great way to promote code reuse.

Classes and Interfaces

An interface is the description of the methods and properties a class will expose “ it's an immutable contract with the outside world. The interface doesn't define any implementation “ just the methods and properties. Derived classes then have to provide the actual implementation.

In Visual Basic .NET you automatically get a default interface that matches the class methods and properties, but there may be times when we want to explicitly define the interface. One good example of this is that when creating .NET-serviced components, the interface can be used to provide versioning features. See Chapter 23 for more details on this.

To create an interface, the Interface construct is used as follows:

  Public Interface IPerson   Property FirstName() As String   Property LastName() As String   Function FullName() As String   End Interface  

As you can see, there is no implementation specified here. By convention, the interface name is the class name preceded by I , although this isn't enforced. To derive a class from an interface, the Implements keyword is used on the class:

  Public Class Person   Implements IPerson     Private _firstName As String   Private _lastName As String     Public Property FirstName() As String Implements IPerson.FirstName   ' implementation goes here   End Property     Public Property LastName() As String Implements IPerson.LastName   ' implementation goes here   End Property     Public Function FullName() As String Implements IPerson.FullName   Return _firstName & " " & _lastName   End Function     End Class  
Note

Both the class, and the methods and properties, have to specify their implementation interface.

Multiple inheritance is allowed only in an interface. For example:

  Public Interface Person   Inherits IPerson   Inherits ICleverPerson   End Interface  

Language Changes

Along with the object-oriented features, there have been many changes to the language. We won't go into exhaustive detail here (it's well covered in the documentation), but here are some things to watch out for:

  • Array bounds :The lower bound of an array is always , and cannot be changed. The Option Base statement is not supported.

  • Array declaration : ReDim can only be used if the array has already been declared.

  • Array sizes :Arrays do not have a fixed size (although the number of dimensions is fixed). For example.

      Dim ConnectionTimes(10) As Date  

    This defines an array with an initial size of 11 elements. Arrays can also be populated on declaration:

      Dim ConnectionTimes() As Date = {"10:30", "11:30", "12:00", "06:00"}  
  • String length :The fixed-width string is not supported unless the VBFixedString attribute is used.

  • Variants :The Variant data type is no longer supported, being replaced by a more generic Object . The corresponding VarType function is also not supported, as the Object has a GetType method.

  • Data types :The Currency data type is replaced by Decimal . The Integer type is now 32 bits, with Short being 16 bits and Long being 64 bits.

  • Short cut operators :A new short form of addition and assignment has been added. For example.

      counter += 1   name &= " Sussman"  
  • Default properties :As mentioned earlier, default properties are not supported, unless they take parameters.

  • Variable declaration :When declaring multiple variables on the same line, a variable with no data type takes the type of the next declared type (and not Variant as was the case in VB6). For example, in the following declarations Age is an Integer .

      Dim Age, Hours As Integer   Dim Name As String, Age, Hours As Integer  
  • Variable scope :Block scope is now supported, so variables declared within blocks (such as If blocks) are only visible within the If block. In Visual Basic 6, variables could be declared anywhere , but their scope was the entire method.

  • Object creation :The As New keywords can be used freely on the variable declaration line. There is no implicit object creation, so objects that are Nothing remain set to Nothing unless an explicit instance is created.

  • Procedure parameters :The rules for parameter passing and optional parameters have changed. See the section on Parameters later for more information on this.

  • Procedure calls :Parentheses are now required on all procedure calls, not just functions.

  • Function return values :The return value from a function is now supplied with the Return statement, rather than by setting the function name to the desired value.

  • While loops :The Wend statement has been replaced with End While .

  • String and Variant functions :The string manipulation functions that had two types of call ( Trim returned a Variant and Trim$ returned a string ) are replaced with overloaded method calls.

  • Empty and Null :The Empty and Null keywords have their functionality replaced by Nothing .

There are many other changes, some of which don't really affect ASP.NET programmers. For a full list, consult the Visual Basic .NET documentation, or see Wrox's Professional VB.NET, 2nd Edition , ISBN: 0-7645-4400-4 .

References

Since you're freed from using a set design tool, some of the features you are used to now require a bit more typing. One example of this is referencing other components. In Visual Basic 6, to access COM components you select References from the Project menu. There's something similar in Visual Studio .NET to reference assemblies (or even COM components), but if you're using Notepad, you have to provide the reference yourself. This is done using the Imports keyword. For example:

  Imports System   Imports MyComponent  

It's also possible to alias references using the following syntax:

  Imports  aliasName  =  Namespace   

If an alias is used, the alias must be included in references to classes that the namespace contains. For example, if you have a namespace called MyComponent containing a class called MyClass , and import the namespace like this:

  Imports foo = MyComponent  

You can't then access the class like this:

  Dim comp As MyClass  

You have to use the following syntax:

  Dim comp As foo.MyClass  

Structured Exception Handling

One of the best new features of .NET is a unified structured exception-handling framework, which extends to Visual Basic .NET. Although On Error is still supported, a far better way of handling errors is to use the new Try Catch Finally structure. The way it works is simple, with each of the statements defining a block of code to be run.

The syntax is:

  Try     ' code block to run     [     Catch [  exception  [As  type  ]] [When  exception  ]     ' code to run if the exception generated matches   ' the exception and expression defined above     [Exit Try]   ]   Catch [  exception  [As.  type  ]] [When  expression  ]   ' code to run if the exception generated matches   ' the exception and expression defined above     [Exit Try]     [Finally   ' code that always runs, whether or not an exception   ' was caught, unless Exit Try is called   ]     End Try  

This allows you to bracket a section of code and then handle generic or specific errors. For example:

  Try   ' connect to a database and   ' retrieve some data   ' ... code left out for clarity ...     Catch exSQL As SQLException   ErrorLabel.Text = "SQL Error: " & exSQL.ToString()     Catch ex As Exception   ErrorLabel.Text = "Other error: " & ex.ToString()     Finally   FinishedLabel.Text = "Finished"     End Try  

You can have multiple Catch blocks, to make our error handling specific to a particular error. Always put the most specific Catch blocks first and the more generic ones last, as the Catch blocks are tried in the order they are declared.

The Throw statement can be used to throw your own errors, or even re-raise errors.

Errors and exceptions are covered in detail in Chapter 22.

Data Types and Structures

There are three new data types:

  • Char : for unsigned 16-bit values.

  • Short : for signed 16-bit integers. This is the equivalent to the current Visual Basic Integer (in Visual Basic .NET the Integer is now 32-bits and the Long 64-bits).

  • Decimal : for signed integers.

Custom types are now provided by the Structure statement, rather than the Type statement. The syntax is:

  [Public  Private  Friend] Structure  structureName    End Structure  

For example:

  Public Structure Person   Public FirstName As String   Public LastName As String   Private Age As Integer   End Structure  

The use of structures is unified with classes, enabling structures to not only contain member variables, but also methods:

  Public Structure Narcissist   Public FirstName As String   Public LastName As String   Private RealAge As Integer     Public Function Age() As Integer   Return RealAge  5   End Function   End Structure  

Whether you use classes or structures is purely a coding and design decision, but the close linking of the two types provides added flexibility.

Parameters

Several things have changed regarding passing parameters to procedures. The most important is that parameters now default to ByVal . To achieve reference parameters, you must explicitly put ByRef in front of the parameter name.

Secondly, as mentioned earlier, all method calls with parameters must be surrounded by parentheses. The previous versions of Visual Basic had the inconsistency that parentheses were required for functions but not subroutines. For example, the following is no longer valid:

  MyMethod 1, 2, "foo"  

Instead, you must use:

  MyMethod(1, 2, "foo")  

For optional parameters, you now have to specify a default, and the IsMissing() method is removed. For example, you cannot write:

  Sub MyMethod(Name As String, Optional Age As Integer)     If IsMissing(Age) Then   ...  

You have to supply a default:

  Sub MyMethod(Name As String, Optional Age As Integer = -1)  

Debugging and Message Boxes

Although not relevant to ASP.NET pages, there are two things that might hit you if you are using Visual Studio .NET:

  • The Print method of the Debug object has been replaced by four methods “ Write() , WriteIf() , WriteLine() , and WriteLineIf() .

  • The MsgBox statement has been replaced with the Show method of the MessageBox object.

Debugging is covered in detail in Chapter 22.

Backward Compatibility

To ease the transition from Visual Basic 6 to Visual Basic .NET, you can reference the Microsoft.VisualBasic.Compatibility.VB6 namespace, which provides access to much of the removed or changed functionality. It's probably best not to overuse these compatibility features, though. The changes to the language have been made not only to improve it, but also to bring it in line with the CLS and the other .NET languages.




Professional ASP. NET 1.1
Professional ASP.NET MVC 1.0 (Wrox Programmer to Programmer)
ISBN: 0470384611
EAN: 2147483647
Year: 2006
Pages: 243

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net