When your code refers to a declared element, the Visual Basic compiler matches the name in your reference to the appropriate declaration of that name. If more than one element is declared with the same name, you can control which of those elements is to be referenced by qualifying its name.
The compiler attempts to match a name reference to a name declaration with the narrowest scope. This means it starts with the code making the reference and works outward through successive levels of containing elements.
The following example shows references to two variables with the same name. The example declares two variables, each named
totalCount, at different levels of scope in module
container. When the procedure
totalCount without qualification, the Visual Basic compiler resolves the reference to the declaration with the narrowest scope, namely the local declaration inside
showCount. When it qualifies
totalCount with the containing module
container, the compiler resolves the reference to the declaration with the broader scope.
' Assume these two modules are both in the same assembly. Module container Public totalCount As Integer = 1 Public Sub showCount() Dim totalCount As Integer = 6000 ' The following statement displays the local totalCount (6000). MsgBox("Unqualified totalCount is " & CStr(totalCount)) ' The following statement displays the module's totalCount (1). MsgBox("container.totalCount is " & CStr(container.totalCount)) End Sub End Module Module callingModule Public Sub displayCount() container.showCount() ' The following statement displays the containing module's totalCount (1). MsgBox("container.totalCount is " & CStr(container.totalCount)) End Sub End Module
Qualifying an Element Name
If you want to override this search process and specify a name declared in a broader scope, you must qualify the name with the containing element of the broader scope. In some cases, you might also have to qualify the containing element.
Qualifying a name means preceding it in your source statement with information that identifies where the target element is defined. This information is called a qualification string. It can include one or more namespaces and a module, class, or structure.
The qualification string should unambiguously specify the module, class, or structure containing the target element. The container might in turn be located in another containing element, usually a namespace. You might need to include several containing elements in the qualification string.
To access a declared element by qualifying its name
Determine the location in which the element has been defined. This might include a namespace, or even a hierarchy of namespaces. Within the lowest-level namespace, the element must be contained in a module, class, or structure.
' Assume the following hierarchy exists outside your code. Namespace outerSpace Namespace innerSpace Module holdsTotals Public Structure totals Public thisTotal As Integer Public Shared grandTotal As Long End Structure End Module End Namespace End Namespace
Determine a qualification path based on the target element's location. Start with the highest-level namespace, proceed to the lowest-level namespace, and end with the module, class, or structure containing the target element. Each element in the path must contain the element that follows it.
Prepare the qualification string for the target element. Place a period (
.) after every element in the path. Your application must have access to every element in your qualification string.
Write the expression or assignment statement referring to the target element in the normal way.
grandTotal = 9000
Precede the target element name with the qualification string. The name should immediately follow the period (
.) that follows the module, class, or structure that contains the element.
' Assume the following module is part of your code. Module accessGrandTotal Public Sub setGrandTotal() outerSpace.innerSpace.holdsTotals.totals.grandTotal = 9000 End Sub End Module
The compiler uses the qualification string to find a clear, unambiguous declaration to which it can match the target element reference.
You might also have to qualify a name reference if your application has access to more than one programming element that has the same name. For example, the System.Windows.Forms and System.Web.UI.WebControls namespaces both contain a
Label class (System.Windows.Forms.Label and System.Web.UI.WebControls.Label). If your application uses both, or if it defines its own
Label class, you must distinguish the different
Label objects. Include the namespace or import alias in the variable declaration. The following example uses the import alias.
' The following statement must precede all your declarations. Imports win = System.Windows.Forms, web = System.Web.UI.WebControls ' The following statement references the Windows.Forms.Label class. Dim winLabel As New win.Label()
Members of Other Containing Elements
When you use a nonshared member of another class or structure, you must first qualify the member name with a variable or expression that points to an instance of the class or structure. In the following example,
demoClass is an instance of a class named
Dim demoClass As class1 = New class1() demoClass.someSub[(argumentlist)]
You cannot use the class name itself to qualify a member that is not Shared. You must first create an instance in an object variable (in this case
demoClass) and then reference it by the variable name.
If a class or structure has a
Shared member, you can qualify that member either with the class or structure name or with a variable or expression that points to an instance.
A module does not have any separate instances, and all its members are
Shared by default. Therefore, you qualify a module member with the module name.
The following example shows qualified references to module member procedures. The example declares two
Sub procedures, both named
perform, in different modules in a project. Each one can be specified without qualification within its own module but must be qualified if referenced from anywhere else. Because the final reference in
module3 does not qualify
perform, the compiler cannot resolve that reference.
' Assume these three modules are all in the same assembly. Module module1 Public Sub perform() MsgBox("module1.perform() now returning") End Sub End Module Module module2 Public Sub perform() MsgBox("module2.perform() now returning") End Sub Public Sub doSomething() ' The following statement calls perform in module2, the active module. perform() ' The following statement calls perform in module1. module1.perform() End Sub End Module Module module3 Public Sub callPerform() ' The following statement calls perform in module1. module1.perform() ' The following statement makes an unresolvable name reference ' and therefore generates a COMPILER ERROR. perform() ' INVALID statement End Sub End Module
References to Projects
To use Public elements defined in another project, you must first set a reference to that project's assembly or type library. To set a reference, click Add Reference on the Project menu, or use the /reference (Visual Basic) command-line compiler option.
For example, you can use the XML object model of the .NET Framework. If you set a reference to the System.Xml namespace, you can declare and use any of its classes, such as XmlDocument. The following example uses XmlDocument.
' Assume this project has a reference to System.Xml ' The following statement creates xDoc as an XML document object. Dim xDoc As System.Xml.XmlDocument
Importing Containing Elements
You can use the Imports Statement (.NET Namespace and Type) to import the namespaces that contain the modules or classes that you want to use. This enables you to refer to the elements defined in an imported namespace without fully qualifying their names. The following example rewrites the previous example to import the System.Xml namespace.
' Assume this project has a reference to System.Xml ' The following statement must precede all your declarations. Imports System.Xml ' The following statement creates xDoc as an XML document object. Dim xDoc As XmlDocument
In addition, the
Imports statement can define an import alias for each imported namespace. This can make the source code shorter and easier to read. The following example rewrites the previous example to use
xD as an alias for the System.Xml namespace.
' Assume this project has a reference to System.Xml ' The following statement must precede all your declarations. Imports xD = System.Xml ' The following statement creates xDoc as an XML document object. Dim xDoc As xD.XmlDocument
Imports statement does not make elements from other projects available to your application. That is, it does not take the place of setting a reference. Importing a namespace just removes the requirement to qualify the names defined in that namespace.
You can also use the
Imports statement to import modules, classes, structures, and enumerations. You can then use the members of such imported elements without qualification. However, you must always qualify nonshared members of classes and structures with a variable or expression that evaluates to an instance of the class or structure.
When you define two or more programming elements that have the same name, a name ambiguity can result when the compiler attempts to resolve a reference to that name. If more than one definition is in scope, or if no definition is in scope, the reference is irresolvable. For an example, see "Qualified Reference Example" on this Help page.
You can avoid name ambiguity by giving all your elements unique names. Then you can make reference to any element without having to qualify its name with a namespace, module, or class. You also reduce the chances of accidentally referring to the wrong element.
When two programming elements share the same name, one of them can hide, or shadow, the other one. A shadowed element is not available for reference; instead, when your code uses the shadowed element name, the Visual Basic compiler resolves it to the shadowing element. For a more detailed explanation with examples, see Shadowing in Visual Basic.