Selected New and Different Visual Basic .NET Topics

Visual Basic .NET is a brave new world for Visual Basic and VBA developers. Understanding this new world can catapult our fortunes far ahead of those who lag behind. However, rising to the top of the developer space is not without its costs. In particular, we have to learn new ways to handle traditional as well as nontraditional topics. There is no better time than right now to learn the concepts discussed in this section because we can expect future versions of Visual Basic .NET to add new functionality at the cost of greater complexity, just as we saw with successive Visual Basic versions. Therefore, learning the basic concepts now will position you to readily digest future advances when they come along.

When I refer to Visual Basic and VBA throughout this section, I am designating the syntax and conventions consistent with Visual Basic 6, which applies to the version of VBA in Microsoft Office 2000 and later editions.

Data Types

As Visual Basic and VBA developers migrate to Visual Basic .NET, it is important to know changes in the names, declaration characters , and recommended usage for 2-byte, 4-byte, and 8-byte signed integer data types. Table 2-2 summarizes the name and declaration type changes for signed integers. Notice that Visual Basic .NET retains the names Integer and Long , but it uses these names for different data types. Visual Basic and VBA developers migrating to Visual Basic .NET gain a new integer data type for large integer data values. You can now represent 8-byte signed integer values with a Long data type.

Table 2-2: Changes for 2-Byte, 4-Byte, and 8-Byte Signed Integers

Integer Size

Visual Basic/VBA Name
(declaration character)

Visual Basic .NET Name
(declaration character)

2 bytes

Integer (%)

Short (not available)

4 bytes

Long (&)

Integer (%)

8 bytes

Not available

Long (&)

The 32-bit systems, such as Microsoft Windows 98 and Windows 2000, process Visual Basic .NET integer data types slightly faster than either of the comparable data types in Table 2-2. Therefore, you can improve performance marginally by using 4-byte integers in development contexts where 2-byte integers were recommended to save memory. A more noticeable performance advantage results from replacing a Decimal data type with an Integer data type, but you must be sure that your range of values does not exceed the Integer data type range.

Another important data type change is the dropping of the Currency data type. In Visual Basic and VBA, this data type represented signed integer values up to an 8-byte length with integer precision scaled for 4 fixed places after the decimal. Visual Basic .NET offers a better Decimal data type than what was available with Visual Basic and VBA. The new Decimal data type represents 16- byte signed integer values with a variable scaling factor as a power of 10. Visual Basic and VBA allowed only up to 12-byte signed integer values in a Decimal value, and you had to represent the values with the CDec function inside a Variant data type. As a result of these changes, Visual Basic .NET developers must use their Decimal data type in contexts in which Visual Basic and VBA developers used the Currency data type. This shift provides greater flexibility in the range and precision of currency values that you can process in Visual Basic .NET vs. Visual Basic/VBA.

The last data type change is the dropping of the Variant data type. In Visual Basic and VBA, if you did not explicitly assign a variable to another data type, it was implicitly designated as a Variant data type. In addition, a Variant data type can hold all other data types. The Object data type in Visual Basic .NET plays a similar role to the Variant data type in Visual Basic and VBA. (The Object data type will be discussed more in Chapter 3.) However, as with the Variant data type, recommended practice is to use a more specific data type designation whenever possible.

Arrays

Because ADO.NET introduces the DataSet class as an in-memory data store, Access developers will have fewer uses for arrays than in the past. Nevertheless, there will be times when you can represent sets of values in memory outside a dataset, such as when there is no database with which to coordinate a set of values or when your application can benefit from representing data in multiple dimensions and the number of dimensions is greater than two.

If you do use arrays in your application development efforts, there are several changes in the way Visual Basic .NET processes arrays from Visual Basic and VBA. First, Visual Basic .NET permits you to declare an array only with a Dim statement. Visual Basic and VBA enabled the declaration of an array with either Dim or ReDim statements. Second, arrays in Visual Basic .NET always have a lower bound of 0. Visual Basic .NET does not support the Option Base statement that enabled Visual Basic and VBA developers to specify a lower bound value of 1 for an array dimension instead of the default value of 0. Third, array sizes are always variable in Visual Basic .NET. You can respecify the size of any array with a ReDim statement in a procedure. In Visual Basic and VBA, you could specify fixed-size arrays, which the ReDim statement could not change.

New Keyword and Sub Procedures

The New keyword in a Dim statement has taken on new and slightly different functionality. In Visual Basic and VBA, declaring an object reference with New allowed you to use the object without an explicit Set statement. In Visual Basic .NET, there is no Set statement. Therefore, you need to use the New keyword in any Dim statement declaring an object reference based on a class. Visual Basic .NET adds extra functionality to the New keyword by allowing it to specify startup parameters for an object in a Dim statement. For example, if you have a chair class, you can specify any of multiple arguments for it when you declare a new chair instance. You can designate its type ( loveseat , patio , recliner ) or fabric ( cloth , leather , plastic ). The syntax for the New keyword in a Dim statement is as follows :

 Dim  VariableName  As New  ClassName  (  comma separated argument list  ) 

The reason you can specify arguments for a class instance is because of a New Sub procedure inside the class library for a class. The .NET Framework refers to this procedure as a class constructor . The .NET Framework constructs a class instance for a code block that invokes the constructor with the New keyword in a Dim statement. If you design a class without explicitly creating a New Sub procedure, Visual Basic .NET implicitly creates one for the class. With the new overloading feature in Visual Basic .NET, you can specify alternative versions of the New Sub procedure ”one for each argument list that you want to make available for defining a class instance at startup. Visual Basic .NET is smart enough to invoke the New Sub procedure that corresponds to the argument list that you provide.

Opening and Closing Class References

Some readers may recognize the New Sub procedure in a class as a substitute for the Class_Initialize event procedure, which you could specify with Visual Basic and VBA. Visual Basic .NET no longer supports the Class_Initialize event. While there are some differences between Class_Initialize event procedures and New Sub procedures, both types of procedures serve one central purpose ”to get a class instance ready for initial use.

Just as there is no Class_Initialize event in Visual Basic .NET, there is no Class_Terminate event. Visual Basic and VBA raised the Class_Terminate event after an instance of a class was set to Nothing . Setting a class to Nothing in Visual Basic and VBA removed the reference for a class instance from memory. Your Visual Basic and VBA code can use a procedure associated with the Class_Terminate event for a class instance to close resources managed by the class instance, such as a file or a database connection. In Visual Basic .NET, setting an object reference to Nothing does not remove a reference to a class instance from memory. Instead, assigning Nothing marks the variable for selection in the next garbage collection cycle. At that time, the common language runtime (CLR) engine removes the reference from memory. Even without your setting an object reference to Nothing , the .NET Framework can evaluate whether to remove the object. Specifically, the garbage collector automatically determines when a class instance is out of scope (can no longer be referenced).

No matter how the .NET Framework discovers when to remove an object reference, the reference is removed nondeterministically. In other words, you cannot know in advance when the memory for a reference will be reclaimed, only that it will be reclaimed eventually. Since garbage collection cycles depend on the memory available on a system and the system load, the time to reclaim the memory for an unused reference can vary between computers with different amounts of memory, or even over time on the same machine as the load shifts by time of day.

So how do you release extra resources associated with a class instance? These extra resources, such as files and database connections, are not automatically closed when the garbage collector cleans up the memory for unused object references. One approach is to invoke Sub Finalize . This is a protected method of the Object class from which all components derive. The .NET Framework invokes the Finalize method whenever it removes a class instance from memory. You can associate code to dispose of extra resources with this class method. Unfortunately, there are several disadvantages associated with using the Finalize method, including a performance penalty, nondeterministic occurrence, and trickier-than-normal rules about when and how to use the method.

A second approach is to close extra resources independently of a class. (For example, invoke the Close method for a database connection associated with a class instance in the application invoking the class.) This can deterministically remove resources associated with a class. Of course, programmers sometimes fail to follow good programming habits, such as invoking the Close method when a resource is not needed. Therefore, it is possible for a programmer to fail to close a file or database connection associated with a class instance. When you are working on very sophisticated systems, you can use the Finaliz e method to close resources not explicitly closed earlier.

Note  

Which approach you should use for removing extra resources associated with a class instance depends on the cost of having the resources not closed in your operational context. In my opinion, the easiest way is to dispose explicitly of extra resources associated with a class instance outside the Finalize method.

Class Inheritance

Inheritance is one of the most exciting new features available with Visual Basic .NET. With this feature, you can have one class inherit the properties, methods , and events of another class. The class that gets inherited is the base class; the class inheriting the base class is called the derived class . When a derived class inherits a base class, the derived class can optionally expose properties, methods, and events from the base class. The derived class can also change the definition of properties and methods or add new properties, methods, and events. A derived class can inherit from only one other class directly, but your applications can have multiple levels of inheritance so that class C can inherit from class B, which inherits from class A. As you begin to build inheritance into your solutions, I recommend keeping your inheritance levels shallow .

Use the Inherits keyword within a class to derive that class from a base class. When you use the Inherits keyword in a derived class, it must be the first line of code in the class. The Inherits keyword takes a single argument, which is the name of the base class. As it turns out, all classes in Visual Basic .NET applications are inherited, except for one. This is the Object class, which is ultimately the base class for all other classes. If you define a class without the Inherits keyword, the class inherits directly from the Object class.

A derived class can change base class members via overriding or shadowing . These two approaches to changing a base class member in a derived class work similarly but not identically. Overriding applies exclusively to Function, Sub , and Property elements in a base class, and the overriding member in the derived class must have the same type and argument list as the base class. In order to override a base class member in a derived class, the base class member must have the Overridable keyword as part of its declaration and the corresponding derived class member must have Overrides as part of its declaration.

Any named type in a derived class can shadow a correspondingly named type in a base class. The derived class type hides the shadowed type in the base class. A procedure of a field in a derived class can shadow either a procedure or a field in a base class. There is no requirement that the shadowing type match the shadowed type. While you can include the Shadows keyword in the derived type declaration, the use of the Shadows keyword is not mandatory. There is no keyword to apply to a base class type declaration that a derived class type shadows.

A derived class may refer to the overridden version of a method or the base class implementation of a method. You can use the MyBase and MyClass keywords to clarify these references. To designate the base class implementation of an overridden method in a derived class, use MyBase.Method1 . To specify the overridden derived class implementation of the same method in the base class, use MyClass.Method1 . If a method is not overridden in a derived class, MyBase.Method1 and MyClass.Method1 return the same result. Both MyBase and MyClass are just keywords, not objects, and are used exclusively with methods.

One of the easiest ways to grasp new programming concepts is to review sample code generated by someone else. Visual Studio .NET puts the Inherits statement and the MyBase keyword to use as it instantiates the form for a Windows application. This code resides in a region in the code module behind the form. By default, the region is collapsed , but you can expand it to see how Windows handles the job of making a new form. In fact, Visual Studio .NET manages the code in this region as you manually add, edit, and remove controls on the form. By examining the code in this region, you can learn a lot about programming techniques for controlling the layout of controls on a form. The string identifying the region is Windows Form Designer Generated Code.

Note  

A region is a block of lines within a code module that you can expand and collapse.

Figure 2-8 displays an excerpt from the top of the completed code module behind the form appearing in Figure 2-6. I inserted the code listed in the Creating and Consuming a Class Library Project section and compiled the application, so there is no asterisk after Form1.vb on the tab for the view. The code excerpt starts with the declaration of a class named Form1 . This is the name of the form that appears when you initially open a Windows application. You can see in Figure 2-8 the syntax for the Inherits statement. In this case, the Windows form in the InvokeAboutInClassLibrary1 project inherits from the Form class in the System.Windows.Forms namespace. After inheriting the class, the code invokes the New method from the Form class. By using the MyBase keyword, the automatically generated code refers back to the code in the Form class. The Forms Designer uses the call to InitializeComponent as a helper routine for the New Sub procedure to create the form instance that initially appears in the Windows application as Form1 .

click to expand
Figure 2-8: An excerpt from the code module behind the form in the InvokeAboutInClassLibrary1 project that illustrates the instantiation of a form

Namespaces

The .NET Framework uses namespaces as a means of organizing the objects in an assembly. The discussion of Figure 2-8 illustrated an application for the System.Windows.Forms namespace. The discussion focused on the Form class within the namespace. However, there are many other classes in the System.Windows.Forms namespace, and adding controls to a form can cause the Forms Designer to create code illustrating how to use it. By default, each assembly has a namespace associated with it (named after the project). However, you can designate multiple namespaces for a single assembly or define a namespace that spans multiple assemblies.

Use the Namespace keyword to define a namespace. Namespaces can contain one or more types, such as classes, and user -defined types known as structures, enumerations, and delegates (which can process events), interfaces, and other namespaces. If you do not explicitly declare a namespace, Visual Basic .NET automatically creates one named after each assembly. Since namespaces are always public, the types within a namespace cannot include any access modifiers, except for Public and Friend; Chapter 3 defines access modifiers, such as Public and Friend , for namespaces of other .NET entities.

The names of types within a namespace must be unique. However, the names of types between namespaces can overlap with one another. By placing the namespace name before the type name, you can unambiguously designate a type even if the same name exists in two or more namespaces.

Note  

It is good to keep life simple. Use just one namespace per assembly unless there are compelling reasons to do otherwise. You can view the default namespace for an assembly based on an .exe file by right-clicking the project file in Solution Explorer and selecting General under Common Properties in the project s Property Pages dialog box. The entry in the Root Namespace box des the root namespace for the project. Clearing this box allows you to specify a new root namespace or multiple root namespaces in the same assembly. Otherwise , all namespaces you designate with the Namespace keyword will have this name as their root.

The Imports keyword enables you to create shortcut names in your applications to refer to namespaces (and even names within them). You must use this keyword at the top of a module directly below any Option statements, such as Option Explicit On . Recall that the InvokeAboutInClassLibrary1 project added a reference to the ClassLibrary1 project, which made the namespace for the ClassLibrary1 project available in the InvokeAboutInClassLibrary1 project. However, to clarify the reference to the Class1 class in the ClassLibrary1 namespace, our preceding sample prefixed the class name with the namespace name. Figure 2-9 shows a modification to the code module behind Form1 in the InvokeAboutInClassLibrary1 project that demonstrates the use of the Imports statement. The sample sets MyClassLib as an alias for the Class1 class in the ClassLibrary1 namespace. The Imports statement at the top of the module shortens the reference to Class1 from ClassLibrary1.Class1 . Figure 2-9 shows the syntax for using the MyClassLib alias in place of the full namespace name and class name.

click to expand
Figure 2-9: A modification to the InvokeAboutInClassLibrary1 project that illustrates the syntax for and use of the Imports keyword
 


Programming Microsoft Visual Basic. NET for Microsoft Access Databases
Programming Microsoft Visual Basic .NET for Microsoft Access Databases (Pro Developer)
ISBN: 0735618194
EAN: 2147483647
Year: 2006
Pages: 111
Authors: Rick Dobson

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