Quelldateien und Namespaces

Ein Visual Basic-Programm besteht aus einer oder mehreren Quelldateien. Wenn ein Programm kompiliert wird, werden alle Quelldateien zusammen verarbeitet. Daher können Quelldateien, möglicherweise in Zirkelform, unabhängig von einer Anforderung zur Forward-Deklaration voneinander abhängen. Die Textreihenfolge der Deklarationen im Programmtext ist im Allgemeinen nicht von Bedeutung.

Eine Quelldatei besteht aus einer optionalen Gruppe von Optionsanweisungen, Importanweisungen und Attributen, auf die ein Namespacetext folgt. Die Attribute, die entweder über den Modifizierer oder Module den Assembly Modifizierer verfügen müssen, gelten für die .NET-Assembly oder das modul, das von der Kompilierung erstellt wird. Der Textkörper der Quelldatei fungiert als implizite Namespacedeklaration für den globalen Namespace, was bedeutet, dass alle Deklarationen auf der obersten Ebene einer Quelldatei im globalen Namespace platziert werden. Beispiel:

FileA.vb:

Class A
End Class

FileB.vb:

Class B
End Class

Die beiden Quelldateien tragen zum globalen Namespace bei, in diesem Fall zwei Klassen mit den vollqualifizierten Namen A und B. Da die beiden Quelldateien zum gleichen Deklarationsraum beitragen, wäre es ein Fehler gewesen, wenn jede eine Deklaration eines Elements mit demselben Namen enthielt.

Hinweis: Die Kompilierungsumgebung kann die Namespacedeklarationen überschreiben, in die eine Quelldatei implizit platziert wird.

Sofern nicht angegeben, können Anweisungen innerhalb eines Visual Basic-Programms entweder durch einen Zeilenterminator oder durch einen Doppelpunkt beendet werden.

Start
    : OptionStatement* ImportsStatement* AttributesStatement* NamespaceMemberDeclaration*
    ;

StatementTerminator
    : LineTerminator
    | ':'
    ;

AttributesStatement
    : Attributes StatementTerminator
    ;

Programmstart und -beendigung

Programmstart tritt auf, wenn die Ausführungsumgebung eine festgelegte Methode ausführt, die als Einstiegspunkt des Programms bezeichnet wird. Diese Einstiegspunktmethode, die immer benannt Mainwerden muss, muss freigegeben werden, darf nicht in einem generischen Typ enthalten sein, darf nicht über den asynchronen Modifizierer verfügen und muss über eine der folgenden Signaturen verfügen:

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

Die Barrierefreiheit der Einstiegspunktmethode ist irrelevant. Wenn ein Programm mehr als einen geeigneten Einstiegspunkt enthält, muss die Kompilierungsumgebung einen als Einstiegspunkt festlegen. Andernfalls tritt ein Kompilierfehler auf. Die Kompilierungsumgebung kann auch eine Einstiegspunktmethode erstellen, wenn keine vorhanden ist.

Wenn ein Programm beginnt, enthält das argument, das von der Ausführungsumgebung bereitgestellte Argument die Befehlszeilenargumente für das Programm, das als Zeichenfolgen dargestellt wird. Wenn der Einstiegspunkt einen Rückgabetyp aufweist Integer, wird der von der Funktion zurückgegebene Wert als Ergebnis des Programms an die Ausführungsumgebung zurückgegeben.

In allen anderen Punkten verhalten sich Einstiegspunktmethoden auf die gleiche Weise wie andere Methoden. Wenn die Ausführung den Aufruf der Einstiegspunktmethode verlässt, die von der Ausführungsumgebung vorgenommen wird, wird das Programm beendet.

Kompilierungsoptionen

Eine Quelldatei kann Kompilierungsoptionen im Quellcode mithilfe von Optionsanweisungen angeben.

OptionStatement
    : OptionExplicitStatement
    | OptionStrictStatement
    | OptionCompareStatement
    | OptionInferStatement
    ;

Eine Option Anweisung gilt nur für die Quelldatei, in der sie angezeigt wird, und nur eine der einzelnen Anweisungstypen Option kann in einer Quelldatei angezeigt werden. Beispiel:

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.

Es gibt vier Kompilierungsoptionen: strenge Typsemantik, explizite Deklarationssemantik, Vergleichssemantik und lokale Variablentyp-Ableitungsemantik. Wenn eine Quelldatei keine bestimmte Option Anweisung enthält, bestimmt die Kompilierungsumgebung, welche bestimmte Semantik verwendet wird. Es gibt auch eine fünfte Kompilierungsoption, ganzzahlige Überlaufüberprüfungen, die nur über die Kompilierungsumgebung angegeben werden können.

Option Explicit-Anweisung

Die Option Explicit Anweisung bestimmt, ob lokale Variablen implizit deklariert werden können. Die Schlüsselwörter On oder Off können der Anweisung folgen. Wenn keines angegeben ist, lautet Onder Standardwert . Wenn keine Anweisung in einer Datei angegeben ist, bestimmt die Kompilierungsumgebung, welche verwendet wird.

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

OnOff
    : 'On' | 'Off'
    ;

Hinweis: Explicit und Off sind keine reservierten Wörter.

Option Explicit Off

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

In diesem Beispiel wird die lokale Variable x implizit durch Zuweisen deklariert. Der Typ von x ist Object.

Option Strict-Anweisung

Die Option Strict Anweisung bestimmt, ob Konvertierungen und Vorgänge Object durch strenge oder zulässige Typsemantik bestimmt werden und ob Typen implizit so eingegeben werden, als Object ob keine As Klausel angegeben wird. Die Anweisung kann von den Schlüsselwörtern On gefolgt werden oder Off; wenn keines angegeben ist, ist Ondie Standardeinstellung . Wenn keine Anweisung in einer Datei angegeben ist, bestimmt die Kompilierungsumgebung, welche verwendet wird.

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

Hinweis: Strict und Off sind keine reservierten Wörter.

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

Unter strenger Semantik sind die folgenden Unzulässigen:

  • Verengung von Konvertierungen ohne expliziten Umwandlungsoperator.

  • Verspätete Bindung.

  • Vorgänge für andere Typen Object als TypeOf...Is, Isund IsNot.

  • Auslassen der Klausel in einer Deklaration, die As keinen abgeleiteten Typ aufweist.

Option Compare-Anweisung

Die Option Compare Anweisung bestimmt die Semantik von Zeichenfolgenvergleichen. Zeichenfolgenvergleiche werden entweder mithilfe binärer Vergleiche durchgeführt (in denen der binäre Unicode-Wert jedes Zeichens verglichen wird) oder Textvergleiche (in denen die lexikalische Bedeutung jedes Zeichens mit der aktuellen Kultur verglichen wird). Wenn keine Anweisung in einer Datei angegeben ist, steuert die Kompilierungsumgebung, welche Art von Vergleich verwendet wird.

OptionCompareStatement
    : 'Option' 'Compare' CompareOption StatementTerminator
    ;

CompareOption
    : 'Binary' | 'Text'
    ;

Hinweis.Compare, Binary, und Text sind keine reservierten Wörter.

Option Compare Text

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

In diesem Fall erfolgt der Zeichenfolgenvergleich mithilfe eines Textvergleichs, der Die Groß-/Kleinschreibungsunterschiede ignoriert. Wenn Option Compare Binary angegeben, dann hätte dies gedruckt Falsewerden sollen.

Ganzzahlige Überlaufüberprüfungen

Ganzzahlige Vorgänge können entweder zur Laufzeit auf Überlaufbedingungen überprüft oder nicht überprüft werden. Wenn Überlaufbedingungen überprüft werden und ein ganzzahliger Vorgang überläuft, wird eine System.OverflowException Ausnahme ausgelöst. Wenn Überlaufbedingungen nicht überprüft werden, löst ganzzahlige Vorgangsüberläufe keine Ausnahme aus. Die Kompilierungsumgebung bestimmt, ob diese Option aktiviert oder deaktiviert ist.

Option Infer-Anweisung

Die Option Infer Anweisung bestimmt, ob lokale Variablendeklarationen ohne As Klausel einen abgeleiteten Typ oder eine Verwendung aufweisen Object. Die Anweisung kann von den Schlüsselwörtern On gefolgt werden oder Off; wenn keines angegeben ist, ist Ondie Standardeinstellung . Wenn keine Anweisung in einer Datei angegeben ist, bestimmt die Kompilierungsumgebung, welche verwendet wird.

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

Hinweis: Infer und Off sind keine reservierten Wörter.

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

Imports-Anweisung

Imports Anweisungen importieren die Namen von Entitäten in eine Quelldatei, sodass auf die Namen ohne Qualifikation verwiesen werden kann, oder importieren Sie einen Namespace für die Verwendung in XML-Ausdrücken.

ImportsStatement
    : 'Imports' ImportsClauses StatementTerminator
    ;

ImportsClauses
    : ImportsClause ( Comma ImportsClause )*
    ;

ImportsClause
    : AliasImportsClause
    | MembersImportsClause
    | XMLNamespaceImportsClause
    ;

Innerhalb von Memberdeklarationen in einer Quelldatei, die eine Imports Anweisung enthält, können die im angegebenen Namespace enthaltenen Typen direkt referenziert werden, wie im folgenden Beispiel gezeigt:

Imports N1.N2

Namespace N1.N2
    Class A
    End Class
End Namespace 

Namespace N3
    Class B
        Inherits A
    End Class
End Namespace

In der Quelldatei sind die Namespace-Typen N1.N2 direkt verfügbar und somit N3.B von der Klasse N1.N2.Aabgeleitet.

Imports Anweisungen müssen nach allen Option Anweisungen, jedoch vor Typdeklarationen angezeigt werden. Die Kompilierungsumgebung kann auch implizite Imports Anweisungen definieren.

Imports Anweisungen stellen Namen in einer Quelldatei zur Verfügung, deklarieren jedoch nichts im Deklarationsbereich des globalen Namespaces. Der Bereich der von einer Imports Anweisung importierten Namen erstreckt sich über die Namespacemememxdeklarationen, die in der Quelldatei enthalten sind. Der Umfang einer Imports Anweisung enthält insbesondere keine anderen Imports Anweisungen und enthält auch keine anderen Quelldateien. Imports Anweisungen beziehen sich möglicherweise nicht aufeinander.

In diesem Beispiel ist die letzte Imports Anweisung fehlerhaft, da sie nicht vom ersten Importalias betroffen ist.

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

Namespace N1.N2
End Namespace

Hinweis: Die Namespace- oder Typnamen, die in Imports Anweisungen angezeigt werden, werden immer so behandelt, als wären sie vollqualifizierte. Das heißt, der ganz links stehende Bezeichner in einem Namespace oder Typnamen wird immer im globalen Namespace aufgelöst, und der Rest der Auflösung wird gemäß normalen Namensauflösungsregeln fortgesetzt. Dies ist der einzige Ort in der Sprache, die eine solche Regel anwendet; Die Regel stellt sicher, dass ein Name nicht vollständig von der Qualifikation ausgeblendet werden kann. Wenn ohne die Regel ein Name im globalen Namespace in einer bestimmten Quelldatei ausgeblendet wurde, wäre es unmöglich, Namen aus diesem Namespace auf qualifizierte Weise anzugeben.

In diesem Beispiel bezieht sich die Imports Anweisung immer auf den globalen System Namespace und nicht auf die Klasse in der Quelldatei.

Imports System   ' Imports the namespace, not the class.

Class System
End Class

Aliase importieren

Ein Importalias definiert einen Alias für einen Namespace oder Typ.

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

Hier ist innerhalb der Quelldatei A ein Alias für N1.N2.A, und somit wird die Klasse N3.B von der Klasse N1.N2.Aabgeleitet. Derselbe Effekt kann durch Erstellen eines Alias R für N1.N2 und anschließendes Verweisen R.Aabgerufen werden:

Imports R = N1.N2

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

Der Bezeichner eines Importalias muss innerhalb des Deklarationsbereichs des globalen Namespace eindeutig sein (nicht nur die globale Namespacedeklaration in der Quelldatei, in der der Importalias definiert ist), obwohl er keinen Namen im Deklarationsraum des globalen Namespace deklariert.

Hinweis: Deklarationen in einem Modul führen keine Namen in das enthaltende Deklarationsraum ein. Daher gilt es für eine Deklaration in einem Modul, denselben Namen wie ein Importalias zu haben, auch wenn auf den Namen der Deklaration im enthaltenden Deklarationsraum zugegriffen werden kann.

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

Class A
End Class

Namespace N3
    Class A
    End Class
End Namespace

Hier enthält der globale Namespace bereits ein Element A, daher ist es ein Fehler für einen Importalias, um diesen Bezeichner zu verwenden. Es handelt sich ebenfalls um einen Fehler für zwei oder mehr Importaliasen in derselben Quelldatei, um Aliase mit demselben Namen zu deklarieren.

Ein Importalias kann einen Alias für einen beliebigen Namespace oder Typ erstellen. Der Zugriff auf einen Namespace oder typ über einen Alias führt genau zum gleichen Ergebnis wie der Zugriff auf den Namespace oder den Typ über den deklarierten Namen.

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

Hier beziehen sich die Namen N1.N2.A, , und R2.A alle beziehen sich auf die Klasse, deren vollqualifizierter Name ist N1.N2.AR1.N2.A.

Der Import gibt den genauen Namen des Namespaces oder Typs an, für den ein Alias erstellt wird. Dies muss der genaue vollqualifizierte Name dieses Namespaces oder Typs sein: Er verwendet nicht die normalen Regeln für die qualifizierte Namensauflösung (die z. B. den Zugriff auf die Member einer Basisklasse über eine abgeleitete Klasse zulassen).

Wenn ein Importalias auf einen Typ oder Namespace verweist, der von diesen Regeln nicht aufgelöst werden kann, wird die Import-Anweisung ignoriert (und der Compiler gibt eine Warnung an).

Außerdem kann der Verweis nicht auf einen offenen generischen Typ sein – alle generischen Typen müssen gültige Typargumente enthalten, und alle Typargumente müssen durch die oben genannten Regeln aufgelöst werden können. Jede falsche Bindung eines generischen Typs ist ein Fehler.

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

Deklarationen in der Quelldatei können den Namen des Importalias schatten.

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

Im vorangehenden Beispiel wird der Verweis in R.A der Deklaration eines B Fehlers ausgelöst, da R auf , nicht N1.N2auf N3.R.

Ein Importalias stellt einen Alias in einer bestimmten Quelldatei zur Verfügung, trägt jedoch nicht zum zugrunde liegenden Deklarationsbereich bei. Mit anderen Worten, ein Importalias ist nicht transitiv, sondern wirkt sich vielmehr nur auf die Quelldatei aus, in der er auftritt.

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

Im obigen Beispiel ist der Umfang des Importalias, R der nur auf Deklarationen in der Quelldatei erweitert wird, in der sie enthalten ist, R in der zweiten Quelldatei unbekannt.

Namespaceimporte

Ein Namespaceimport importiert alle Member eines Namespaces oder Typs, sodass der Bezeichner jedes Elements des Namespaces oder Typs ohne Qualifikation verwendet werden kann. Bei Typen ermöglicht ein Namespaceimport nur den Zugriff auf die freigegebenen Member des Typs, ohne dass die Qualifikation des Klassennamens erforderlich ist. Insbesondere können die Member von Aufzählungstypen ohne Qualifikation verwendet werden.

MembersImportsClause
    : TypeName
    ;

Beispiel:

Imports Colors

Enum Colors
    Red
    Green
    Blue
End Enum

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

Im Gegensatz zu einem Importalias hat ein Namespaceimport keine Einschränkungen für die importierten Namen und kann Namespaces und Typen importieren, deren Bezeichner bereits im globalen Namespace deklariert sind. Die von einem regulären Import importierten Namen werden durch Importalias und Deklarationen in der Quelldatei schattiert.

Im folgenden Beispiel bezieht sich nicht N3.AN1.N2.A auf Memberdeklarationen im N3 Namespace, A sondern auf Memberdeklarationen.

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

Wenn mehr als ein importierter Namespace Member mit demselben Namen enthält (und dieser Name andernfalls nicht durch einen Importalias oder eine Deklaration schattiert wird), ist ein Verweis auf diesen Namen mehrdeutig und verursacht einen Kompilierungszeitfehler.

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

Im obigen Beispiel enthalten beide N1 member und N2 enthalten ein Element A. Da N3 beide importiert werden, führt das Verweisen A in N3 einem Kompilierungsfehler zu einem Kompilierzeitfehler. In dieser Situation kann der Konflikt entweder durch die Qualifizierung von Verweisen Aauf oder durch Einführung eines Importalias gelöst werden, der einen bestimmten AAlias auswählt, wie im folgenden Beispiel:

Imports N1
Imports N2
Imports A = N1.A

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

Es können nur Namespaces, Klassen, Strukturen, aufgezählte Typen und Standardmodule importiert werden.

XML-Namespaceimporte

Ein XML-Namespaceimport definiert einen Namespace oder den Standardnamespace für nicht qualifizierte XML-Ausdrücke, die in der Kompilierungseinheit enthalten sind.

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

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

Beispiel:

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

Ein XML-Namespace, einschließlich des Standardnamespaces, kann nur einmal für eine bestimmte Gruppe von Importen definiert werden. Beispiel:

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

Namespaces

Visual Basic-Programme werden mithilfe von Namespaces organisiert. Namespaces organisieren sowohl intern ein Programm als auch die Art und Weise, wie Programmelemente für andere Programme verfügbar gemacht werden.

Im Gegensatz zu anderen Entitäten sind Namespaces offen beendet und können mehrmals innerhalb desselben Programms und in vielen Programmen deklariert werden, wobei jede Deklaration Member zum gleichen Namespace beiträgt. Im folgenden Beispiel tragen die beiden Namespacedeklarationen zum gleichen Deklarationsraum bei, wobei zwei Klassen mit vollqualifizierten Namen N1.N2.A deklariert werden.N1.N2.B

Namespace N1.N2
    Class A
    End Class
End Namespace

Namespace N1.N2
    Class B
    End Class
End Namespace

Da die beiden Deklarationen zum gleichen Deklarationsbereich beitragen, wäre es ein Fehler, wenn jede eine Deklaration eines Elements mit demselben Namen enthielt.

Es gibt einen globalen Namespace, der keinen Namen hat und auf dessen geschachtelte Namespaces und Typen ohne Qualifikation immer zugegriffen werden kann. Der Bereich eines namespace-Members, der im globalen Namespace deklariert ist, ist der gesamte Programmtext. Andernfalls ist der Bereich eines Typs oder Namespaces, der in einem Namespace deklariert ist, dessen vollqualifizierter Name der Programmtext jedes Namespaces istN, dessen vollqualifizierter Name mit oder N selbst beginntN. (Beachten Sie, dass ein Compiler Deklarationen standardmäßig in einen bestimmten Namespace einfügen kann. Dies ändert nicht die Tatsache, dass es immer noch einen globalen, unbenannten Namespace gibt.)

In diesem Beispiel kann die Klasse die Klasse BA sehen, da Bder Namespace N1.N2.N3 konzeptuell im Namespace N1.N2geschachtelt ist.

Namespace N1.N2
    Class A
    End Class
End Namespace

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

Namespacedeklarationen

Es gibt drei Formen der Namespacedeklaration.

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

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

RelativeNamespaceName
    : Identifier ( Period IdentifierOrKeyword )*
    ;

Das erste Formular beginnt mit dem Schlüsselwort Namespace gefolgt von einem relativen Namespacenamen. Wenn der relative Namespacename qualifiziert ist, wird die Namespacedeklaration so behandelt, als wäre sie lexikalisch in Namespacedeklarationen geschachtelt, die jedem Namen im qualifizierten Namen entsprechen. Die folgenden beiden Namespaces sind z. B. semantisch gleichwertig:

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

Das zweite Formular beginnt mit den Schlüsselwörtern Namespace Global. Es wird behandelt, als ob alle Memberdeklarationen lexikalisch im globalen unbenannten Namespace platziert wurden – unabhängig von den Standardwerten, die von der Kompilierungsumgebung bereitgestellt werden. Diese Form der Namespacedeklaration ist möglicherweise nicht lexikalisch in einer anderen Namespacedeklaration geschachtelt.

Das dritte Formular beginnt mit den Schlüsselwörtern Namespace Global , gefolgt von einem qualifizierten Bezeichner N. Es wird behandelt, als ob es sich um eine Namespacedeklaration des ersten Formulars "Namespace N" handelte, die lexikalisch im globalen unbenannten Namespace platziert wurde – unabhängig von den Von der Kompilierungsumgebung bereitgestellten Standardwerten. Diese Form der Namespacedeklaration ist möglicherweise nicht lexikalisch in einer anderen Namespacedeklaration geschachtelt.

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

Beim Umgang mit den Membern eines Namespaces ist es nicht wichtig, wenn ein bestimmtes Element deklariert wird. Wenn zwei Programme eine Entität mit demselben Namen im selben Namespace definieren, verursacht der Versuch, den Namen im Namespace zu beheben, einen Mehrdeutigkeitsfehler.

Namespaces sind per Definition Public, sodass eine Namespacedeklaration keine Zugriffsmodifizierer enthalten kann.

Namespace-Elemente

Namespacember können nur Namespacedeklarationen und Typdeklarationen sein. Typdeklarationen verfügen Public möglicherweise über oder Friend haben Zugriff. Der Standardzugriff für Typen ist Friend der Zugriff.

NamespaceMemberDeclaration
    : NamespaceDeclaration
    | TypeDeclaration
    ;

TypeDeclaration
    : ModuleDeclaration
    | NonModuleDeclaration
    ;

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