类型提升 (Visual Basic)
当你在模块中声明某个编程元素时,Visual Basic 会将该元素的作用域提升为包含该模块的命名空间。 这称为类型提升。
以下示例演示了某个模块的骨架定义以及该模块的两个成员。
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
在 projModule
中,在模块级别声明的编程元素将提升为 projNamespace
。 以上示例中提升了 basicEnum
和 innerClass
,但未提升 numberSub
,因为它不是在模块级别声明的。
类型提升的效果
类型提升的效果是限定字符串不需要包含模块名称。 以下示例对前面示例中的过程发出两次调用。
Sub usePromotion()
projNamespace.projModule.innerClass.numberSub(projNamespace.projModule.basicEnum.one)
projNamespace.innerClass.numberSub(projNamespace.basicEnum.two)
End Sub
在以上示例中,第一个调用使用完整的限定字符串。 但由于类型提升,不需要这样做。 第二个调用还会访问模块的成员,但不会将 projModule
包含在限定字符串中。
类型提升失败
如果命名空间已有一个与模块成员同名的成员,则对该模块成员进行类型提升将会失败。 以下示例演示了同一命名空间中某个枚举和模块的骨架定义。
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
在以上示例中,Visual Basic 无法将类 abc
提升为 thisNameSpace
,因为在命名空间级别已存在同名的枚举。 若要访问 abcSub
,必须使用完整的限定字符串 thisNamespace.thisModule.abc.abcSub
。 但是,类 xyz
仍会提升,你可以使用较短的限定字符串 thisNamespace.xyz.xyzSub
来访问 xyzSub
。
不完整类型的类型提升失败
如果模块内的某个类或结构使用 Partial 关键字,则对该类或结构进行类型提升会自动失效,而不管命名空间是否包含同名的成员。 模块中的其他元素仍可进行类型提升。
后果。 不完整定义的类型提升失败可能会导致意外结果甚至编译器错误。 以下示例演示了某个类的骨架不完整定义,其中一个定义在模块内部。
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
在以上示例中,开发人员可能希望编译器合并 sampleClass
的两个不完整定义。 但是,编译器不考虑 sampleModule
内的不完整定义的提升。 因此,它会尝试编译两个独立且不同的类,这两个类均命名为 sampleClass
,但具有不同的限定路径。
仅当其完全限定的路径相同时,编译器才将合并分部定义。
建议
以下建议陈述了良好的编程做法。
唯一名称。 如果你可以完全控制编程元素的命名,在每个位置使用唯一的名称始终是不错的想法。 相同的名称需要进行额外的限定,因而会使代码更难以阅读。 相同的名称还可能导致不易察觉的错误和意外的结果。
完全限定。 在同一个命名空间中处理模块和其他元素时,最安全的做法是始终对所有编程元素使用完全限定。 如果对某个模块成员进行类型提升失败并且未完全限定该成员,可能会无意中访问不同的编程元素。