Visual Basic 2005 with .NET 3.0 Programmer's Reference

Normally, Visual Basic does a pretty good job of resolving namespaces, and you don’t need to worry too much about the process. If you import a namespace, you can omit the namespace in any declarations that you use. If you have not imported a namespace, you can fully qualify declarations that use the namespace and you’re done. There are some in-between cases, however, that can be confusing. To understand them, it helps to know a bit more about how Visual Basic resolves namespaces.

When Visual Basic sees a reference that uses a fully qualified namespace, it looks in that namespace for the item it needs and that’s that. It either succeeds or fails. For example, the following code declares a variable of type System.Collections.Hashtable. Visual Basic looks in the System.Collections namespace and tries to find the Hashtable class. If the class is not there, the declaration fails.

Dim hash_table As New System.Collections.Hashtable

When Visual Basic encounters a qualified namespace, it first assumes that it is fully qualified. If it cannot resolve the reference as described in the previous paragraph, it tries to treat the reference as partially qualified and it looks in the current namespace for a resolution. For example, suppose you declare a variable as shown in the following code:

Dim emp As JobClasses.Employee

In this case, Visual Basic searches the current namespace for a nested namespace called JobClasses. If it finds such a namespace, it looks for the Employee class in that namespace.

If Visual Basic cannot resolve a namespace using these methods, it moves up the namespace hierarchy and tries again. For example, suppose that the current code is in the MyApplication.JobStuff.EmployeeClasses .TimeSheetRoutines namespace. Now, suppose that the SalaryLevel class is defined in the MyApplication .JobStuff namespace and consider the following code:

Dim salary_level As New SalaryLevel

Visual Basic examines the current namespace MyApplication.JobStuff.EmployeeClasses .TimeSheet Routines and doesn’t find a definition for SalaryLevel. It moves up the namespace hierarchy and searches the MyApplication.JobStuff.EmployeeClasses namespace, again failing to find SalaryLevel. It moves up the hierarchy again to the MyApplication.JobStuff namespace, and there it finally finds the SalaryLevel class.

Movement up the namespace hierarchy can sometimes be a bit confusing. It may lead Visual Basic to resolve references in an ancestor of the current namespace, in some sort of “uncle/aunt” namespace, or in a “cousin” namespace.

For example, consider the namespace hierarchy shown in Figure 17-5. The root namespace MyApplication contains the namespaces BusinessClasses and AssignmentStuff. BusinessClasses defines the Employee and Customer classes. AssignmentStuff contains the AssignmentGlobals module, which defines the MakeAssignment subroutine and a different version of the Employee class.

Figure 17-5: Visual Basic may search all over the namespace hierarchy to resolve a declaration.

Now, suppose that the Customer class contains the following subroutine:

Public Sub AssignEmployee() AssignmentStuff.AssignmentGlobals.MakeAssignment(Me) ... End Sub

This code lies in the MyApplication.BusinessClasses namespace. Visual Basic cannot find a meaning for the AssignmentStuff namespace locally in that context, so it moves up the namespace hierarchy to

MyApplication, where it finds the AssignmentStuff namespace. Within that namespace, it finds the AssignmentGlobals module and the MakeAssignment subroutine that it contains.

Visual Basic can also peer into modules as if their public contents were part of the namespace itself. That means you can rewrite the previous code in the following slightly simpler version:

Public Sub AssignEmployee() AssignmentStuff.MakeAssignment(Me) ... End Sub

In this example, there is only one MakeAssignment subroutine, so there’s little doubt that Visual Basic has found the correct one. If different namespaces define items with the same names, the situation can be somewhat more confusing. Suppose that the Customer class declares an object that is from the Employee class defined in the MyApplication.AssignmentStuff namespace, as shown in the following code:

Dim emp As New AssignmentStuff.Employee

If you understand how Visual Basic performs namespace resolution, you can figure out that the object is of the Employee class defined in the MyApplication.AssignmentStuff namespace. This isn’t completely obvious, however.

If you add an Imports statements to the program, the situation gets more confusing. Suppose that the program imports the AssignmentStuff namespace and then the Customer class declares a variable of type Employee. Because this code is in the BusinessClasses namespace, Visual Basic uses that namespace’s version of Employee. If the code is in some other namespace (such as MyApplication), the program uses the imported AssignmentStuff version of the class.

Finally, suppose that the program imports both BusinessClasses and AssignmentStuff.AssignmentGlobals and then makes the following declaration in another namespace. In this case, Visual Basic cannot decide which version of the class to use, so it generates an error.

Dim emp As Employee

This example is so confusing, however, that you would probably be better off restructuring the namespaces and possibly renaming one of the versions of the Employee class rather than trying to figure out how Visual Basic is resolving the namespaces.

You can simplify these issues by avoiding duplicate names across all namespaces. When you do use duplicate namespaces, you can use fully qualified namespaces to avoid ambiguity. You can also use Imports statements to make namespace aliases and then use the aliases to avoid ambiguity more concisely.

Категории