Pliki źródłowe i przestrzenie nazw

Program Visual Basic składa się z co najmniej jednego pliku źródłowego. Po skompilowaniu programu wszystkie pliki źródłowe są przetwarzane razem; w związku z tym pliki źródłowe mogą zależeć od siebie, być może w sposób okrągły, bez żadnego wymagania dotyczącego deklaracji dalej. Tekstowa kolejność deklaracji w tekście programu jest ogólnie nie ma znaczenia.

Plik źródłowy składa się z opcjonalnego zestawu instrukcji opcji, instrukcji importu i atrybutów, po których następuje treść przestrzeni nazw. Atrybuty, które muszą mieć Assembly lub Module modyfikator, mają zastosowanie do zestawu lub modułu platformy .NET utworzonego przez kompilację. Treść pliku źródłowego działa jako niejawna deklaracja przestrzeni nazw dla globalnej przestrzeni nazw, co oznacza, że wszystkie deklaracje na najwyższym poziomie pliku źródłowego są umieszczane w globalnej przestrzeni nazw. Przykład:

FileA.vb:

Class A
End Class

FileB.vb:

Class B
End Class

Dwa pliki źródłowe współtworzyją globalną przestrzeń nazw, w tym przypadku deklarując dwie klasy z w pełni kwalifikowanymi nazwami A i B. Ponieważ dwa pliki źródłowe współtworzyją tę samą przestrzeń deklaracji, byłby to błąd, gdyby każdy zawierał deklarację elementu członkowskiego o tej samej nazwie.

Uwaga. Środowisko kompilacji może zastąpić deklaracje przestrzeni nazw, w których plik źródłowy jest niejawnie umieszczany.

Z wyjątkiem przypadków, w których zanotowano, instrukcje w programie Visual Basic można zakończyć za pomocą terminatora wiersza lub dwukropka.

Start
    : OptionStatement* ImportsStatement* AttributesStatement* NamespaceMemberDeclaration*
    ;

StatementTerminator
    : LineTerminator
    | ':'
    ;

AttributesStatement
    : Attributes StatementTerminator
    ;

Uruchamianie i kończenie działania programu

Uruchamianie programu występuje, gdy środowisko wykonywania wykonuje wyznaczoną metodę, która jest określana jako punkt wejścia programu. Ta metoda punktu wejścia, która musi być zawsze nazwana Main, musi być współużytkowany, nie może być zawarta w typie ogólnym, nie może mieć modyfikatora asynchronicznego i musi mieć jeden z następujących podpisów:

Sub Main()
Sub Main(args() As String)
Function Main() As Integer
Function Main(args() As String) As Integer

Dostępność metody punktu wejścia nie ma znaczenia. Jeśli program zawiera więcej niż jeden odpowiedni punkt wejścia, środowisko kompilacji musi wyznaczyć jeden jako punkt wejścia. W przeciwnym razie wystąpi błąd czasu kompilacji. Środowisko kompilacji może również utworzyć metodę punktu wejścia, jeśli nie istnieje.

Po rozpoczęciu programu, jeśli punkt wejścia ma parametr, argument dostarczony przez środowisko wykonywania zawiera argumenty wiersza polecenia do programu reprezentowane jako ciągi. Jeśli punkt wejścia ma zwracany typ Integer, wartość zwrócona z funkcji jest zwracana do środowiska wykonawczego w wyniku programu.

We wszystkich innych kwestiach metody punktu wejścia zachowują się w taki sam sposób, jak inne metody. Gdy wykonanie opuszcza wywołanie metody punktu wejścia przez środowisko wykonawcze, program kończy działanie.

Opcje kompilacji

Plik źródłowy może określać opcje kompilacji w kodzie źródłowym przy użyciu instrukcji opcji.

OptionStatement
    : OptionExplicitStatement
    | OptionStrictStatement
    | OptionCompareStatement
    | OptionInferStatement
    ;

Instrukcja Option ma zastosowanie tylko do pliku źródłowego, w którym się pojawia, i tylko jeden z każdego typu instrukcji Option może pojawić się w pliku źródłowym. Przykład:

Option Strict On
Option Compare Text
Option Strict Off    ' Not allowed, Option Strict is already specified.
Option Compare Text  ' Not allowed, Option Compare is already specified.

Istnieją cztery opcje kompilacji: semantyka typu ścisłego, semantyka jawnej deklaracji, semantyka porównania i semantyka lokalnego typu zmiennej semantyki wnioskowania. Jeśli plik źródłowy nie zawiera określonej Option instrukcji, środowisko kompilacji określa, który zestaw semantyki będzie używany. Istnieje również piąta opcja kompilacji, sprawdzanie przepełnienia liczby całkowitej, które można określić tylko za pośrednictwem środowiska kompilacji.

Option Explicit, instrukcja

Instrukcja Option Explicit określa, czy zmienne lokalne mogą być niejawnie zadeklarowane. Słowa kluczowe On lub Off mogą być zgodne z instrukcją ; jeśli żadna z nich nie jest określona, wartość domyślna to On. Jeśli w pliku nie określono instrukcji, środowisko kompilacji określa, które będzie używane.

OptionExplicitStatement
    : 'Option' 'Explicit' OnOff? StatementTerminator
    ;

OnOff
    : 'On' | 'Off'
    ;

Uwaga. Explicit i Off nie są słowami zarezerwowanymi.

Option Explicit Off

Module Test
    Sub Main()
        x = 5 ' Valid because Option Explicit is off.
    End Sub
End Module

W tym przykładzie zmienna x lokalna jest niejawnie zadeklarowana przez przypisanie do niej. Typ to xObject.

Option Strict, instrukcja

Instrukcja Option Strict określa, czy konwersje i operacje na Object są zarządzane przez semantyka typu ścisłego lub permissywnego oraz czy typy są niejawnie typizowane tak, jakby Object nie As określono klauzuli. Po instrukcji mogą występować słowa kluczowe On lub Off; jeśli nie określono żadnej z nich, wartość domyślna to On. Jeśli w pliku nie określono instrukcji, środowisko kompilacji określa, które będzie używane.

OptionStrictStatement
    : 'Option' 'Strict' OnOff? StatementTerminator
    ;

Uwaga. Strict i Off nie są słowami zarezerwowanymi.

Option Strict On

Module Test
    Sub Main()
        Dim x ' Error, no type specified.
        Dim o As Object
        Dim b As Byte = o ' Error, narrowing conversion.

        o.F() ' Error, late binding disallowed.
        o = o + 1 ' Error, addition is not defined on Object.
    End Sub
End Module

W ramach ścisłej semantyki następujące elementy są niedozwolone:

  • Zawężanie konwersji bez jawnego operatora rzutowania.

  • Opóźnione powiązanie.

  • Operacje na typie Object innym niż TypeOf...Is, Is, i IsNot.

  • Pominięcie klauzuli As w deklaracji, która nie ma wywnioskowany typ.

Option Compare, instrukcja

Instrukcja Option Compare określa semantyka porównań ciągów. Porównania ciągów są przeprowadzane przy użyciu porównań binarnych (w których porównywana jest binarna wartość Unicode każdego znaku) lub porównań tekstowych (w których znaczenie leksykalne każdego znaku jest porównywane przy użyciu bieżącej kultury). Jeśli w pliku nie określono instrukcji, środowisko kompilacji steruje typem porównania.

OptionCompareStatement
    : 'Option' 'Compare' CompareOption StatementTerminator
    ;

CompareOption
    : 'Binary' | 'Text'
    ;

Uwaga.Compare, Binary, i Text nie są zastrzeżonych wyrazów.

Option Compare Text

Module Test
    Sub Main()
        Console.WriteLine("a" = "A")    ' Prints True.
    End Sub
End Module

W tym przypadku porównanie ciągów odbywa się przy użyciu porównania tekstu, które ignoruje różnice wielkości liter. Gdyby Option Compare Binary został określony, zostanie to wydrukowane False.

Kontrole przepełnienia liczby całkowitej

Operacje liczb całkowitych można sprawdzić lub nie sprawdzać pod kątem warunków przepełnienia w czasie wykonywania. Jeśli warunki przepełnienia są sprawdzane, a operacja całkowita przepełnia się, zgłaszany System.OverflowException jest wyjątek. Jeśli warunki przepełnienia nie są sprawdzane, przepełnienie operacji całkowitej nie zgłasza wyjątku. Środowisko kompilacji określa, czy ta opcja jest włączona, czy wyłączona.

Option Infer, instrukcja

Instrukcja Option Infer określa, czy deklaracje zmiennych lokalnych, które nie As mają klauzuli, mają wywnioskowany typ, czy używać .Object Po instrukcji mogą występować słowa kluczowe On lub Off; jeśli nie określono żadnej z nich, wartość domyślna to On. Jeśli w pliku nie określono instrukcji, środowisko kompilacji określa, które będzie używane.

OptionInferStatement
    : 'Option' 'Infer' OnOff? StatementTerminator
    ;

Uwaga. Infer i Off nie są słowami zarezerwowanymi.

Option Infer On

Module Test
    Sub Main()
        ' The type of x is Integer
        Dim x = 10

        ' The type of y is String
        Dim y = "abc"
    End Sub
End Module

Import, instrukcja

Imports instrukcje importuje nazwy jednostek do pliku źródłowego, umożliwiając przywołowanie nazw bez kwalifikacji lub importowanie przestrzeni nazw do użycia w wyrażeniach XML.

ImportsStatement
    : 'Imports' ImportsClauses StatementTerminator
    ;

ImportsClauses
    : ImportsClause ( Comma ImportsClause )*
    ;

ImportsClause
    : AliasImportsClause
    | MembersImportsClause
    | XMLNamespaceImportsClause
    ;

W deklaracjach składowych w pliku źródłowym, który zawiera instrukcję Imports , typy zawarte w danej przestrzeni nazw można odwoływać się bezpośrednio, jak pokazano w poniższym przykładzie:

Imports N1.N2

Namespace N1.N2
    Class A
    End Class
End Namespace 

Namespace N3
    Class B
        Inherits A
    End Class
End Namespace

Tutaj, w pliku źródłowym, składowe typu przestrzeni nazw N1.N2 są dostępne bezpośrednio, a tym samym klasy N3.B pochodzą z klasy N1.N2.A.

Imports instrukcje muszą pojawiać się po każdej Option instrukcji, ale przed wszelkimi deklaracjami typów. Środowisko kompilacji może również definiować niejawne Imports instrukcje.

Imports instrukcje udostępniają nazwy w pliku źródłowym, ale nie deklarują niczego w przestrzeni deklaracji globalnej przestrzeni nazw. Zakres nazw importowanych przez instrukcję Imports rozszerza się na deklaracje elementów członkowskich przestrzeni nazw zawarte w pliku źródłowym. Zakres instrukcji Imports nie obejmuje również innych Imports instrukcji ani innych plików źródłowych. Imports instrukcje mogą nie odnosić się do siebie nawzajem.

W tym przykładzie ostatnia Imports instrukcja jest błędna, ponieważ nie ma na nią wpływu pierwszy alias importu.

Imports R1 = N1 ' OK.
Imports R2 = N1.N2 ' OK.
Imports R3 = R1.N2 ' Error: Can't refer to R1.

Namespace N1.N2
End Namespace

Uwaga. Przestrzeń nazw lub nazwy typów wyświetlane w Imports instrukcjach są zawsze traktowane tak, jakby były w pełni kwalifikowane. Oznacza to, że najbardziej lewy identyfikator w przestrzeni nazw lub nazwie typu zawsze jest rozpoznawany w globalnej przestrzeni nazw, a reszta rozpoznawania jest kontynuowana zgodnie z normalnymi regułami rozpoznawania nazw. Jest to jedyne miejsce w języku, który stosuje taką regułę; reguła zapewnia, że nazwa nie może być całkowicie ukryta przed kwalifikacjami. Bez reguły, jeśli nazwa w globalnej przestrzeni nazw była ukryta w określonym pliku źródłowym, nie będzie można określić żadnych nazw z tej przestrzeni nazw w sposób kwalifikowany.

W tym przykładzie Imports instrukcja zawsze odwołuje się do globalnej System przestrzeni nazw, a nie do klasy w pliku źródłowym.

Imports System   ' Imports the namespace, not the class.

Class System
End Class

Importowanie aliasów

Alias importu definiuje alias dla przestrzeni nazw lub typu.

AliasImportsClause
    : Identifier Equals TypeName
    ;
Imports A = N1.N2.A

Namespace N1.N2
    Class A
    End Class
End Namespace

Namespace N3
    Class B
        Inherits A
    End Class
End Namespace

W tym miejscu w pliku A źródłowym element jest aliasem klasy N1.N2.A, a zatem klasa N3.B pochodzi z klasy N1.N2.A. Ten sam efekt można uzyskać, tworząc alias R dla elementu N1.N2 , a następnie odwołując R.Asię do elementu :

Imports R = N1.N2

Namespace N3
    Class B
        Inherits R.A
    End Class
End Namespace

Identyfikator aliasu importu musi być unikatowy w przestrzeni deklaracji globalnej przestrzeni nazw (nie tylko globalnej deklaracji przestrzeni nazw w pliku źródłowym, w którym zdefiniowano alias importu), mimo że nie deklaruje nazwy w przestrzeni deklaracji globalnej przestrzeni nazw.

Uwaga. Deklaracje w module nie wprowadzają nazw do zawierającej przestrzeni deklaracji. W związku z tym deklaracja w module ma taką samą nazwę jak alias importu, mimo że nazwa deklaracji będzie dostępna w przestrzeni zawierającej deklarację.

' Error: Alias A conflicts with typename A
Imports A = N3.A

Class A
End Class

Namespace N3
    Class A
    End Class
End Namespace

W tym miejscu globalna przestrzeń nazw zawiera już element członkowski A, więc jest to błąd podczas importowania aliasu do użycia tego identyfikatora. Jest to również błąd dla co najmniej dwóch aliasów importu w tym samym pliku źródłowym, aby zadeklarować aliasy o tej samej nazwie.

Alias importu może utworzyć alias dla dowolnej przestrzeni nazw lub typu. Uzyskiwanie dostępu do przestrzeni nazw lub typu za pośrednictwem aliasu daje dokładnie taki sam wynik, jak uzyskiwanie dostępu do przestrzeni nazw lub typu za pośrednictwem zadeklarowanej nazwy.

Imports R1 = N1
Imports R2 = N1.N2

Namespace N1.N2
    Class A
    End Class
End Namespace

Namespace N3
    Class B
        Private a As N1.N2.A
        Private b As R1.N2.A
        Private c As R2.A
    End Class
End Namespace

W tym miejscu nazwy N1.N2.A, R1.N2.Ai R2.A są równoważne, a wszystkie odnoszą się do klasy, której w pełni kwalifikowana nazwa to N1.N2.A.

Import określa dokładną nazwę przestrzeni nazw lub typu, do którego tworzy alias. Musi to być dokładnie w pełni kwalifikowana nazwa tej przestrzeni nazw lub typu: nie używa normalnych reguł dla kwalifikowanego rozpoznawania nazw (które na przykład zezwalają na dostęp do składowych klasy bazowej za pośrednictwem klasy pochodnej).

Jeśli alias importu wskazuje typ lub przestrzeń nazw, której nie można rozpoznać za pomocą tych reguł, instrukcja import jest ignorowana (a kompilator wyświetla ostrzeżenie).

Ponadto nie można odwoływać się do otwartego typu ogólnego — wszystkie typy ogólne muszą mieć podane prawidłowe argumenty typu, a wszystkie argumenty typu muszą być rozpoznawane przez powyższe reguły. Każde nieprawidłowe powiązanie typu ogólnego jest błędem.

Imports A = G              ' error: since G is an open generic type
Imports B = G(Of Integer)  ' okay
Imports C = Derived.Nested ' warning: Derived.Nested isn't itself a type
Imports D = G(Of Derived.Nested) ' error: Derived.Nested isn't found

Class G(Of T) : End Class

Class Base
    Class Nested : End Class
End Class

Class Derived : Inherits Base
End Class

Module Module1
    Sub Main()
        Dim x As C               ' error: "C" wasn't succesfully defined
        Dim y As Derived.Nested  ' okay
    End Sub
End Module

Deklaracje w pliku źródłowym mogą w tle nazwa aliasu importu.

Imports R = N1.N2

Namespace N1.N2
    Class A
    End Class
End Namespace

Namespace N3
    Class R
    End Class

    Class B
        Inherits R.A  ' Error, R has no member A
    End Class
End Namespace

W poprzednim przykładzie odwołanie do R.A w deklaracji B powoduje błąd, ponieważ R odnosi się do N3.R, a nie N1.N2.

Alias importu udostępnia alias w określonym pliku źródłowym, ale nie współtworzy żadnych nowych elementów członkowskich do bazowej przestrzeni deklaracji. Innymi słowy alias importu nie jest przechodni, ale ma wpływ tylko na plik źródłowy, w którym występuje.

File1.vb:

Imports R = N1.N2

Namespace N1.N2
    Class A
    End Class
End Namespace

File2.vb:

Class B
    Inherits R.A ' Error, R unknown.
End Class

W powyższym przykładzie, ponieważ zakres aliasu importu, który wprowadza R , rozszerza się tylko na deklaracje w pliku źródłowym, w którym jest zawarty, R jest nieznany w drugim pliku źródłowym.

Importy przestrzeni nazw

Import przestrzeni nazw importuje wszystkie elementy członkowskie przestrzeni nazw lub typu, co umożliwia korzystanie z identyfikatora każdego elementu członkowskiego przestrzeni nazw lub typu bez kwalifikacji. W przypadku typów import przestrzeni nazw zezwala tylko na dostęp do udostępnionych elementów członkowskich typu bez konieczności kwalifikacji nazwy klasy. W szczególności umożliwia ona używanie elementów członkowskich wyliczonych typów bez kwalifikacji.

MembersImportsClause
    : TypeName
    ;

Przykład:

Imports Colors

Enum Colors
    Red
    Green
    Blue
End Enum

Module M1
    Sub Main()
        Dim c As Colors = Red
    End Sub
End Module

W przeciwieństwie do aliasu importu import przestrzeni nazw nie ma żadnych ograniczeń dotyczących importowanych nazw i może importować przestrzenie nazw i typy, których identyfikatory są już zadeklarowane w globalnej przestrzeni nazw. Nazwy importowane przez regularny import są w tle importowane przez aliasy importu i deklaracje w pliku źródłowym.

W poniższym przykładzie A odwołuje się do N3.A deklaracji elementów członkowskich zamiast N1.N2.A w deklaracjach składowych N3 w przestrzeni nazw.

Imports N1.N2

Namespace N1.N2
    Class A
    End Class
End Namespace

Namespace N3
    Class A
    End Class

    Class B
        Inherits A
    End Class
End Namespace

Jeśli więcej niż jedna zaimportowana przestrzeń nazw zawiera elementy członkowskie o tej samej nazwie (i ta nazwa nie jest w inny sposób w tle przez alias importu lub deklarację), odwołanie do tej nazwy jest niejednoznaczne i powoduje błąd czasu kompilacji.

Imports N1
Imports N2

Namespace N1
    Class A
    End Class
End Namespace 

Namespace N2
    Class A
    End Class
End Namespace 

Namespace N3
    Class B
        Inherits A ' Error, A is ambiguous.
    End Class
End Namespace

W powyższym przykładzie oba N1 elementy i N2 zawierają element członkowski A. Ponieważ N3 importuje oba, odwołanie A w metodzie powoduje N3 błąd czasu kompilacji. W takiej sytuacji konflikt można rozwiązać za pomocą kwalifikacji odwołań do A, lub wprowadzając alias importu, który wybiera określony Aelement , jak w poniższym przykładzie:

Imports N1
Imports N2
Imports A = N1.A

Namespace N3
    Class B
        Inherits A ' A means N1.A.
    End Class
End Namespace

Importowane mogą być tylko przestrzenie nazw, klasy, struktury, typy wyliczane i standardowe moduły.

Importy przestrzeni nazw XML

Import przestrzeni nazw XML definiuje przestrzeń nazw lub domyślną przestrzeń nazw dla niekwalifikowanych wyrażeń XML zawartych w jednostce kompilacji.

XMLNamespaceImportsClause
    : '<' XMLNamespaceAttributeName XMLWhitespace? Equals XMLWhitespace?
      XMLNamespaceValue '>'
    ;

XMLNamespaceValue
    : DoubleQuoteCharacter XMLAttributeDoubleQuoteValueCharacter* DoubleQuoteCharacter
    | SingleQuoteCharacter XMLAttributeSingleQuoteValueCharacter* SingleQuoteCharacter
    ;

Przykład:

Imports <xmlns:db="http://example.org/database">

Module Test
    Sub Main()
        ' db namespace is "http://example.org/database"
        Dim x = <db:customer><db:Name>Bob</></>

        Console.WriteLine(x.<db:Name>)
    End Sub
End Module

Przestrzeń nazw XML, w tym domyślna przestrzeń nazw, można zdefiniować tylko raz dla określonego zestawu importów. Przykład:

Imports <xmlns:db="http://example.org/database-one">
' Error: namespace db is already defined
Imports <xmlns:db="http://example.org/database-two">

Przestrzenie nazw

Programy Visual Basic są zorganizowane przy użyciu przestrzeni nazw. Przestrzenie nazw zarówno wewnętrznie organizują program, jak i organizują sposób, w jaki elementy programu są widoczne dla innych programów.

W przeciwieństwie do innych jednostek przestrzenie nazw są otwarte i mogą być deklarowane wiele razy w ramach tego samego programu i w wielu programach, a każda deklaracja współtworzenia elementów członkowskich do tej samej przestrzeni nazw. W poniższym przykładzie dwie deklaracje przestrzeni nazw przyczyniają się do tej samej przestrzeni deklaracji, deklarując dwie klasy z w pełni kwalifikowanymi nazwami N1.N2.A i N1.N2.B.

Namespace N1.N2
    Class A
    End Class
End Namespace

Namespace N1.N2
    Class B
    End Class
End Namespace

Ponieważ dwie deklaracje przyczyniają się do tej samej przestrzeni deklaracji, byłby to błąd, jeśli każda zawiera deklarację elementu członkowskiego o tej samej nazwie.

Istnieje globalna przestrzeń nazw, która nie ma nazwy i których zagnieżdżone przestrzenie nazw i typy są zawsze dostępne bez kwalifikacji. Zakres elementu członkowskiego przestrzeni nazw zadeklarowany w globalnej przestrzeni nazw to cały tekst programu. W przeciwnym razie zakres typu lub przestrzeni nazw zadeklarowanej w przestrzeni nazw, której w pełni kwalifikowana nazwa jest N tekstem programu każdego obszaru nazw, którego w pełni kwalifikowana nazwa przestrzeni nazw zaczyna się N od lub jest N sama. (Należy pamiętać, że kompilator może domyślnie umieszczać deklaracje w określonej przestrzeni nazw. Nie zmienia to faktu, że nadal istnieje globalna, nienazwana przestrzeń nazw).

W tym przykładzie klasa B może zobaczyć klasę A , ponieważ Bprzestrzeń nazw N1.N2.N3 jest koncepcyjnie zagnieżdżona w przestrzeni nazw N1.N2.

Namespace N1.N2
    Class A
    End Class
End Namespace

Namespace N1.N2.N3
    Class B
        Inherits A
    End Class
End Namespace

Deklaracje przestrzeni nazw

Istnieją trzy formy deklaracji przestrzeni nazw.

NamespaceDeclaration
    : 'Namespace' NamespaceName StatementTerminator
      NamespaceMemberDeclaration*
      'End' 'Namespace' StatementTerminator
    ;

NamespaceName
    : RelativeNamespaceName
    | 'Global'
    | 'Global' '.' RelativeNamespaceName
    ;

RelativeNamespaceName
    : Identifier ( Period IdentifierOrKeyword )*
    ;

Pierwszy formularz rozpoczyna się od słowa kluczowego Namespace , po którym następuje względna nazwa przestrzeni nazw. Jeśli względna nazwa przestrzeni nazw jest kwalifikowana, deklaracja przestrzeni nazw jest traktowana tak, jakby była zagnieżdżona leksycznie w deklaracjach przestrzeni nazw odpowiadających każdej nazwie w kwalifikowanej nazwie. Na przykład następujące dwie przestrzenie nazw są semantycznie równoważne:

Namespace N1.N2
    Class A
    End Class

    Class B
    End Class
End Namespace 

Namespace N1
    Namespace N2
        Class A
        End Class

        Class B
        End Class
    End Namespace
End Namespace

Drugi formularz rozpoczyna się od słów kluczowych Namespace Global. Jest traktowana tak, jakby wszystkie jego deklaracje składowe zostały umieszczone w globalnej przestrzeni nazw bez nazwy — niezależnie od ustawień domyślnych dostarczonych przez środowisko kompilacji. Ta forma deklaracji przestrzeni nazw może nie być zagnieżdżona leksykalnie w żadnej innej deklaracji przestrzeni nazw.

Trzeci formularz rozpoczyna się od słów kluczowych Namespace Global , po których następuje kwalifikowany identyfikator N. Jest ona traktowana tak, jakby była deklaracją przestrzeni nazw pierwszego formularza "Namespace N", który został leksykalnie umieszczony w globalnej przestrzeni nazw bez nazwy — niezależnie od ustawień domyślnych dostarczonych przez środowisko kompilacji. Ta forma deklaracji przestrzeni nazw może nie być zagnieżdżona leksykalnie w żadnej innej deklaracji przestrzeni nazw.

Namespace Global       ' Puts N1.A in the global namespace
    Namespace N1
        Class A
        End Class
    End Namespace
End Namespace

Namespace Global.N1    ' Equivalent to the above
    Class A
    End Class
End Namespace

Namespace N1           ' May or may not be equivalent to the above,
    Class A            ' depending on defaults provided by the
    End Class          ' compilation environment
End Namespace

W przypadku czynienia z członkami przestrzeni nazw nie jest ważne, gdy określony element członkowski jest zadeklarowany. Jeśli dwa programy definiują jednostkę o tej samej nazwie w tej samej przestrzeni nazw, próba rozpoznania nazwy w przestrzeni nazw powoduje błąd niejednoznaczności.

Przestrzenie nazw mają definicję Public, więc deklaracja przestrzeni nazw nie może zawierać żadnych modyfikatorów dostępu.

Elementy członkowskie przestrzeni nazw

Elementy członkowskie przestrzeni nazw mogą być deklaracjami przestrzeni nazw i deklaracjami typów. Deklaracje typów mogą mieć Public dostęp lub Friend mieć do tego dostęp. Domyślny dostęp dla typów to Friend dostęp.

NamespaceMemberDeclaration
    : NamespaceDeclaration
    | TypeDeclaration
    ;

TypeDeclaration
    : ModuleDeclaration
    | NonModuleDeclaration
    ;

NonModuleDeclaration
    : EnumDeclaration
    | StructureDeclaration
    | InterfaceDeclaration
    | ClassDeclaration
    | DelegateDeclaration
    ;