Type Promotion (Visual Basic)

When you declare a programming element in a module, Visual Basic promotes its scope to the namespace containing the module. This is known as type promotion.

The following example shows a skeleton definition of a module and two members of that module.

Namespace projNamespace
    Module projModule
        Public Enum basicEnum As Integer
            one = 1
            two = 2
        End Enum
        Public Class innerClass
            Shared Sub numberSub(ByVal firstArg As Integer)
            End Sub
        End Class
    End Module
End Namespace

Within projModule, programming elements declared at module level are promoted to projNamespace. In the preceding example, basicEnum and innerClass are promoted, but numberSub is not, because it is not declared at module level.

Effect of Type Promotion

The effect of type promotion is that a qualification string does not need to include the module name. The following example makes two calls to the procedure in the preceding example.

Sub usePromotion()
    projNamespace.projModule.innerClass.numberSub(projNamespace.projModule.basicEnum.one)
    projNamespace.innerClass.numberSub(projNamespace.basicEnum.two)
End Sub

In the preceding example, the first call uses complete qualification strings. However, this is not necessary because of type promotion. The second call also accesses the module's members without including projModule in the qualification strings.

Defeat of Type Promotion

If the namespace already has a member with the same name as a module member, type promotion is defeated for that module member. The following example shows a skeleton definition of an enumeration and a module within the same namespace.

Namespace thisNamespace
    Public Enum abc
        first = 1
        second
    End Enum
    Module thisModule
        Public Class abc
            Public Sub abcSub()
            End Sub
        End Class
        Public Class xyz
            Public Sub xyzSub()
            End Sub
        End Class
    End Module
End Namespace

In the preceding example, Visual Basic cannot promote class abc to thisNameSpace because there is already an enumeration with the same name at namespace level. To access abcSub, you must use the full qualification string thisNamespace.thisModule.abc.abcSub. However, class xyz is still promoted, and you can access xyzSub with the shorter qualification string thisNamespace.xyz.xyzSub.

Defeat of Type Promotion for Partial Types

If a class or structure inside a module uses the Partial keyword, type promotion is automatically defeated for that class or structure, whether or not the namespace has a member with the same name. Other elements in the module are still eligible for type promotion.

Consequences. Defeat of type promotion of a partial definition can cause unexpected results and even compiler errors. The following example shows skeleton partial definitions of a class, one of which is inside a module.

Namespace sampleNamespace
    Partial Public Class sampleClass
        Public Sub sub1()
        End Sub
    End Class
    Module sampleModule
        Partial Public Class sampleClass
            Public Sub sub2()
            End Sub
        End Class
    End Module
End Namespace

In the preceding example, the developer might expect the compiler to merge the two partial definitions of sampleClass. However, the compiler does not consider promotion for the partial definition inside sampleModule. As a result, it attempts to compile two separate and distinct classes, both named sampleClass but with different qualification paths.

The compiler merges partial definitions only when their fully qualified paths are identical.

Recommendations

The following recommendations represent good programming practice.

  • Unique Names. When you have full control over the naming of programming elements, it is always a good idea to use unique names everywhere. Identical names require extra qualification and can make your code harder to read. They can also lead to subtle errors and unexpected results.

  • Full Qualification. When you are working with modules and other elements in the same namespace, the safest approach is to always use full qualification for all programming elements. If type promotion is defeated for a module member and you do not fully qualify that member, you could inadvertently access a different programming element.

See also