Freigeben über


Globale using-Anweisung

Anmerkung

Dieser Artikel ist eine Featurespezifikation. Die Spezifikation dient als Designdokument für das Feature. Es enthält vorgeschlagene Spezifikationsänderungen sowie Informationen, die während des Entwurfs und der Entwicklung des Features erforderlich sind. Diese Artikel werden veröffentlicht, bis die vorgeschlagenen Spezifikationsänderungen abgeschlossen und in die aktuelle ECMA-Spezifikation aufgenommen werden.

Es kann einige Abweichungen zwischen der Featurespezifikation und der abgeschlossenen Implementierung geben. Diese Unterschiede werden in den entsprechenden Hinweisen zum Language Design Meeting (LDM) erfasst.

Weitere Informationen zum Einführen von Featurespezifikationen in den C#-Sprachstandard finden Sie im Artikel zu den Spezifikationen.

Champion-Problem: https://github.com/dotnet/csharplang/issues/3428

Die Syntax für eine using-Anweisung wird mit einem optionalen global-Schlüsselwort erweitert, das dem Schlüsselwort using vorangestellt werden kann.

compilation_unit
    : extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

global_using_directive
    : global_using_alias_directive
    | global_using_namespace_directive
    | global_using_static_directive
    ;

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;
    
global_using_static_directive
    : 'global' 'using' 'static' type_name ';'
    ;
  • Die global_using_directive-Elemente sind nur auf der Kompilierungseinheitsebene zulässig (sie können nicht innerhalb einer namespace_declaration verwendet werden).
  • Die global_using_directive-Elemente, falls vorhanden, müssen allen using_directive-Elementen vorangestellt werden.
  • Der Bereich von global_using_directive erstreckt sich über die namespace_member_declaration-Elemente aller Kompilierungseinheiten innerhalb des Programms. Der Bereich von global_using_directive schließt ausdrücklich keine anderen global_using_directive-Elemente ein. Daher beeinflussen sich die global_using_directive-Elemente des Peers oder solche aus einer anderen Kompilierungseinheit nicht gegenseitig, und die Reihenfolge, in der sie geschrieben werden, ist unbedeutend. Der Umfang einer global_using_directive schließt insbesondere keine using_directive-Elemente ein, die unmittelbar in einer beliebigen Kompilierungseinheit des Programms enthalten sind.

Die Auswirkung des Hinzufügens von global_using_directive zu einem Programm kann als der Effekt des Hinzufügens eines ähnlichen using_directive-Elements, das in denselben Ziel-Namespace oder Typ aufgelöst wird, zu jeder Kompilierungseinheit des Programms betrachtet werden. Das Ziel von global_using_directive wird jedoch im Kontext der Kompilierungseinheit aufgelöst, die es enthält.

§7.7 Bereiche

Dies sind die relevanten Aufzählungspunkte mit den vorgeschlagenen Ergänzungen (die fett formatiert sind).

  • Der durch extern_alias_directive definierte Namensbereich erstreckt sich über die global_using_directive-Elemente,using_directive-Elemente, global_attributes und namespace_member_declaration-Elemente der unmittelbar enthaltenen Kompilationseinheit oder des Namespacetexts. extern_alias_directive fügt dem zugrunde liegenden Deklarationsbereich keine neuen Member hinzu. Mit anderen Worten: Ein extern_alias_directive ist nicht transitiv, sondern wirkt sich vielmehr nur auf die Kompilierungseinheit oder den Namespace-Körper aus, in dem er auftritt.
  • Der Bereich eines durch global_using_directive definierten oder importierten Namens erstreckt sich über die global_attributes und namespace_member_declaration-Elemente aller compilation_unit-Elemente im Programm.

§7.8 Namespace- und Typnamen

Änderungen werden am Algorithmus vorgenommen, der die Bedeutung einer namespace_or_type_name wie folgt bestimmt.

Dies ist der relevante Aufzählungspunkt mit vorgeschlagenen Ergänzungen (die fett formatiert sind):

  • Wenn namespace_or_type_name die Form I oder die Form I<A1, ..., Ak> hat:
    • Wenn K null ist und die namespace_or_type_name in einer generischen Methodendeklaration (§15.6) angezeigt wird und wenn diese Deklaration einen Typparameter (§15.2.3) mit dem Namen Ienthält, bezieht sich die namespace_or_type_name auf diesen Typparameter.
    • Andernfalls, wenn namespace_or_type_name in einer Typdeklaration angezeigt wird, dann gilt für jeden Instanztyp T (§15.3.2), beginnend mit dem Instanztyp dieser Typdeklaration und fortgesetzt mit dem Instanztyp jeder eingeschlossenen Klasse oder Strukturdeklaration (falls vorhanden):
      • Wenn K null ist und die Deklaration von T einen Typparameter mit dem Namen Ienthält, bezieht sich die namespace_or_type_name auf diesen Typparameter.
      • Andernfalls, wenn der namespace_or_type_name im Textkörper der Typdeklaration angezeigt wird und T oder eines seiner Basistypen einen geschachtelten barrierefreien Typ mit Namen I und K Typparametern enthalten, bezieht sich die namespace_or_type_name auf diesen Typ, der mit den angegebenen Typargumenten erstellt wurde. Wenn mehr als ein solcher Typ vorhanden ist, wird der innerhalb des abgeleiteten Typs deklarierte Typ ausgewählt. Beachten Sie, dass Nicht-Typ-Member (Konstanten, Felder, Methoden, Eigenschaften, Indexer, Operatoren, Instanzkonstruktoren, Destruktoren und statische Konstruktoren) und Typmember mit einer anderen Anzahl von Typparametern ignoriert werden, wenn die Bedeutung der namespace_or_type_namebestimmt wird.
    • Wenn die vorherigen Schritte nicht erfolgreich waren, werden für jeden Namespace Nfolgende Schritte durchgeführt: beginnend mit dem Namespace, in dem namespace_or_type_name auftritt, weiter mit jedem eingeschlossenen Namespace (falls vorhanden) und endend mit dem globalen Namespace, werden diese Schritte ausgewertet, bis eine Entität gefunden wird.
      • Wenn K null ist und I der Name eines Namespace in Nist, dann:
        • Wenn der Speicherort, an dem namespace_or_type_name auftritt, durch eine Namespacedeklaration für N eingeschlossen wird und die Namespacedeklaration ein extern_alias_directive- oder using_alias_directive-Element enthält, das den Namen I einem Namespace oder Typ zuordnet, oder eine Namespacedeklaration für N im Programm ein global_using_alias_directive-Element enthält, das den Namen I einem Namespace oder Typ zuordnet, dann ist namespace_or_type_name mehrdeutig und verursacht einen Fehler zu Kompilierungszeit.
        • Andernfalls bezieht sich die namespace_or_type_name auf den Namespace namens I in N.
      • Andernfalls, wenn N einen zugänglichen Typ mit Namen I und K Typparametern enthält, dann:
        • Wenn K null ist und der Speicherort, an dem namespace_or_type_name auftritt, durch eine Namespacedeklaration für N eingeschlossen wird und die Namespacedeklaration ein extern_alias_directive- oder using_alias_directive-Element enthält, das den Namen I einem Namespace oder Typ zuordnet, oder eine beliebige Namespacedeklaration für N im Programm ein global_using_alias_directive-Element enthält, das den Namen I einem Namespace oder Typ zuordnet, dann ist namespace_or_type_name mehrdeutig und verursacht einen Fehler zu Kompilierungszeit.
        • Andernfalls bezieht sich die namespace_or_type_name auf den Typ, der mit den angegebenen Typargumenten erstellt wurde.
      • Wenn der Speicherort, an dem namespace_or_type_name auftritt, von einer Namespacedeklaration für N eingeschlossen ist:
        • Wenn K null ist und die Namespacedeklaration ein extern_alias_directive- oder using_alias_directive-Element enthält, das den Namen I einem importierten Namespace oder Typ zuordnet, oder eine beliebige Namespacedeklaration für N im Programm ein global_using_alias_directive-Element enthält, das den Namen I einem importierten Namespace oder Typ zuordnet, dann bezieht sich namespace_or_type_name auf diesen Namespace oder Typ.
        • Andernfalls, wenn die Namespaces und Typdeklarationen, die von den using_namespace_directive-Elementen und using_alias_directive-Elementen der Namespacedeklaration importiert werden, und die Namespaces und Typdeklarationen, die von den global_using_namespace_directive-Elementen und global_using_static_directive-Elementen von einer beliebigen Namespacedeklaration für N im Programm importiert werden, genau einen zugreifbaren Typ mit dem Paramater für den Namen I und den Typ K enthalten, dann bezieht sich namespace_or_type_name auf diesen Typ, der mit den angegebenen Typargumenten erstellt wurde.
        • Andernfalls, wenn die Namespaces und Typdeklarationen, die von den using_namespace_directive-Elementen und using_alias_directive-Elementen der Namespacedeklaration importiert werden, und die Namespaces und Typdeklarationen, die von den global_using_namespace_directive-Elementen und global_using_static_directive-Elementen von einer beliebigen Namespacedeklaration für N im Programm importiert werden, genau einen zugreifbaren Typ mit dem Parameter für den Namen I und den Typ K enthalten, dann ist namespace_or_type_name nicht eindeutig, und ein Fehler tritt auf.
    • Andernfalls ist die namespace_or_type_name nicht definiert, und ein Kompilierungszeitfehler tritt auf.

Einfache Namen §12.8.4

Änderungen an den simple_name Auswertungsregeln werden wie folgt vorgenommen.

Dies ist der relevante Aufzählungspunkt mit vorgeschlagenen Ergänzungen (die fett formatiert sind):

  • Andernfalls werden für jeden Namespace N ab dem Namespace, in dem simple_name enthalten ist, über jeden umschließenden Namespace (wenn zutreffend) bis zum globalen Namespace die folgenden Schritte ausgewertet, bis eine Entität gefunden wird:
    • Wenn K null ist und I der Name eines Namespace in Nist, dann:
      • Wenn der Speicherort, an dem simple_name auftritt, durch eine Namespacedeklaration für N eingeschlossen wird und die Namespacedeklaration eine extern_alias_directive oder using_alias_directive enthält, die den Namen I einem Namespace oder Typ zuordnet, enthält oder eine Namespacedeklaration für N im Programm eine global_using_alias_directive, die den Namen I einem Namespace oder Typ zuordnet, dann ist simple_name mehrdeutig und verursacht einen Fehler zu Kompilierzeit.
      • Andernfalls bezieht sich die simple_name auf den Namespace namens I in N.
    • Andernfalls, wenn N einen zugänglichen Typ mit Namen I und K Typparameter hat, dann:
      • Wenn K null ist und der Speicherort, an dem simple_name auftritt, durch eine Namespacedeklaration für N eingeschlossen wird und die Namespacedeklaration eine extern_alias_directive oder using_alias_directive enthält, die den Namen I einem Namespace oder Typ zuordnet, oder eine Namespacedeklaration für N im Programm eine global_using_alias_directive enthält, die den Namen I einem Namespace oder Typ zuordnet, dann ist simple_name mehrdeutig und verursacht einen Fehler zur Kompilierzeit.
      • Andernfalls bezieht sich die namespace_or_type_name auf den Typ, der mit den angegebenen Typargumenten erstellt wurde.
    • Andernfalls, wenn der Ort, an dem der simple_name auftritt, von einer Namespacedeklaration für N eingeschlossen wird:
      • Wenn K null ist und die Namespacedeklaration eine extern_alias_directive oder using_alias_directive enthält, die den Namen I einem importierten Namespace oder Typ zuordnet, oder eine beliebige Namespacedeklaration für N im Programm eine global_using_alias_directive enthält, die den Namen I einem importierten Namespace oder Typ zuordnet, dann bezieht sich simple_name auf diesen Namespace oder Typ.
      • Andernfalls, wenn die Namespaces und Typdeklarationen, die von den using_namespace_directive-Elementen und using_static_directive-Elementen der Namespacedeklaration importiert werden, und die Namespaces und Typdeklarationen, die von den global_using_namespace_directive-Elementen und global_using_static_directive-Elementen von einer beliebigen Namespacedeklaration für N im Programm importiert werden, enthalten genau einen zugreifbaren Typ oder ein statisches Member ohne Erweiterung mit dem Parameter für den Namen I und den Typ K, dann bezieht sich simple_name auf diesen Typ oder dieses Member, der bzw. das mit den angegebenen Typargumenten erstellt wurde.
      • Andernfalls, wenn die Namespaces und Typen, die von den using_namespace_directive-Elementen der Namespacedeklaration importiert werden, und die Namespaces und Typdeklarationen, die von den global_using_namespace_directive-Elementen und global_using_static_directive-Elementen von einer beliebigen Namespacedeklaration für N im Programm importiert werden, enthalten genau einen zugreifbaren Typ oder ein statisches Member ohne Erweiterungsmethode mit dem Parameter für den Namen I und den Typ K, dann ist simple_name nicht eindeutig, und ein Fehler tritt auf.

Erweiterungsmethodeaufrufe §12.8.10.3

Änderungen werden am Algorithmus vorgenommen, um die besten type_nameC wie folgt zu finden. Dies ist der relevante Aufzählungspunkt mit vorgeschlagenen Ergänzungen (die fett formatiert sind):

  • Beginnend mit der nächstgelegenen umschließenden Namespacedeklaration, fortlaufend mit jeder eingeschlossenen Namespacedeklaration und endend mit der enthaltenden Kompilierungseinheit, werden aufeinander folgende Versuche unternommen, einen Kandidatensatz von Erweiterungsmethoden zu finden:
    • Wenn die angegebene Namespace- oder Kompilierungseinheit direkt nicht generische Typdeklarationen Ci mit berechtigten Erweiterungsmethoden Mjenthält, ist der Satz dieser Erweiterungsmethoden der Kandidatensatz.
    • Wenn Ci-Typen, die von using_static_declarations importiert wurden und direkt in Namespaces deklariert sind, die von using_namespace_directive-Elementen in den angegebenen Namespace oder in die Kompilierungseinheit importiert werden, und wenn die enthaltene Kompilierungseinheit erreicht wird, die von global_using_static_declarations importiert wurde und direkt in Namespaces deklariert wird, die von global_using_namespace_directive-Elementen im Programm importiert werden und direkt berechtigte Erweiterungsmethoden Mj enthalten, dann ist die Menge dieser Erweiterungsmethoden die Kandidatenmenge.

Kompilierungseinheiten §14.2

Ein compilation_unit definiert die Gesamtstruktur einer Quelldatei. Eine Kompilierungseinheit besteht aus null oder mehr global_using_directive-Elementen, gefolgt von null oder mehr using_directive-Elementen, gefolgt von null oder mehr global_attributes und schließlich gefolgt von null oder mehr namespace_member_declaration-Elementen.

compilation_unit
    : extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

Ein C#-Programm besteht aus einer oder mehreren Kompilierungseinheiten, die jeweils in einer separaten Quelldatei enthalten sind. Wenn ein C#-Programm kompiliert wird, werden alle Kompilierungseinheiten zusammen verarbeitet. So können Kompilierungseinheiten voneinander abhängig sein, möglicherweise in kreisförmiger Weise.

Die global_using_directive-Elemente einer Kompilierungseinheit wirken sich auf die global_attributes und namespace_member_declaration-Elemente aller Kompilierungseinheiten im Programm aus.

Externe Aliase §14.4

Der durch extern_alias_directive definierte Bereich erstreckt sich über die global_using_directive-Elemente,using_directive-Elemente, global_attributes und namespace_member_declaration-Elemente der unmittelbar enthaltenen Kompilationseinheit oder des Namespacetexts.

Verwenden von Aliasdirektiven §14.5.2

Die Reihenfolge, in der using_alias_directive-Elemente geschrieben werden, hat keine Bedeutung, und die Auflösung des namespace_or_type_name-Elements, auf das von using_alias_directive verwiesen wird, ist nicht von using_alias_directive selbst oder von anderen using_directive-Elementen in der unmittelbar enthaltenden Kompilierungseinheit oder im Namespacetext betroffen, und wenn using_alias_directive unmittelbar in einer Kompilierungseinheit enthalten ist, ist es von den global_using_directive-Elementen im Programm nicht betroffen. Mit anderen Worten, namespace_or_type_name eines using_alias_directive-Elements wird so aufgelöst, als ob die unmittelbar enthaltende Kompilierungseinheit oder der Namespacetext keine using_directive-Elemente hat, und wenn using_alias_directive unmittelbar in einer Kompilierungseinheit enthalten ist, hat das Programm keine global_using_directive-Elemente. using_alias_directive kann jedoch durch extern_alias_directive-Elemente in der unmittelbar enthaltenen Kompilierungseinheit oder im Namespacetext beeinflusst werden.

Globale using alias-Anweisungen

global_using_alias_directive führt einen Bezeichner ein, der als Alias für einen Namespace oder Typ innerhalb des Programms dient.

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

Innerhalb von Memberdeklarationen in einer beliebigen Kompilierungseinheit eines Programms, das ein global_using_alias_directive-Element enthält, kann der von global_using_alias_directive eingeführte Bezeichner verwendet werden, um auf den angegebenen Namespace oder Typ zu verweisen.

Der Bezeichner eines global_using_alias_directive-Elements muss innerhalb des Deklarationsbereichs einer beliebigen Kompilationseinheit eines Programms eindeutig sein, das global_using_alias_directive enthält.

Genau wie normale Member werden Namen, die von global_using_alias_directive-Elementen eingeführt wurden, von ähnlich benannten Membern in geschachtelten Bereichen ausgeblendet.

Die Reihenfolge, in der global_using_alias_directive-Elemente geschrieben werden, hat keine Bedeutung, und die Auflösung des namespace_or_type_name-Elements, auf das von global_using_alias_directive verwiesen wird, ist von global_using_alias_directive selbst oder von anderen global_using_directive-Elementen oder using_directive-Elementen im Programm nicht betroffen. Mit anderen Worten: namespace_or_type_name eines global_using_alias_directive-Elements wird so aufgelöst, als ob die unmittelbar enthaltende Kompilierungseinheit keine using_directive-Elemente und das gesamte enthaltende Programm keine global_using_directive-Elemente hatte. global_using_alias_directive kann jedoch durch extern_alias_directive-Elemente in der unmittelbar enthaltenen Kompilierungseinheit beeinflusst werden.

global_using_alias_directive 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 diesen Namespace oder Typ über seinen deklarierten Namen.

Die Verwendung von Aliasen kann einen geschlossenen konstruierten Typ benennen, aber keine ungebundene generische Typdeklaration ohne Angabe von Typargumenten benennen.

Globale using namespace-Anweisungen

Ein global_using_namespace_directive importiert die in einem Namespace enthaltenen Typen in das Programm, sodass der Bezeichner jedes Typs ohne Qualifikation verwendet werden kann.

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;

Innerhalb von Memberdeklarationen in einem Programm, das ein global_using_namespace_directive-Element enthält, können die im angegebenen Namespace enthaltenen Typen direkt referenziert werden.

Ein global_using_namespace_directive importiert die im angegebenen Namespace enthaltenen Typen, importiert jedoch keine geschachtelten Namespaces.

Im Gegensatz zu einem global_using_alias_directivekann ein global_using_namespace_directive Typen importieren, deren Bezeichner bereits in einer Kompilierungseinheit des Programms definiert sind. In einer bestimmten Kompilierungseinheit werden Namen, die durch ein beliebiges global_using_namespace_directive-Element im Programm importiert werden, von ähnlich benannten Membern in der Kompilierungseinheit ausgeblendet.

Wenn mehrere Namespaces oder Typen, die von global_using_namespace_directives oder global_using_static_directives im selben Programm importiert werden, Typen mit demselben Namen enthalten, werden Verweise auf diesen Namen als type_name als mehrdeutig angesehen.

Wenn in einem Programm mehr als ein Namespace oder Typ, der durch global_using_namespace_directives oder global_using_static_directives importiert wird, Typen oder Mitglieder mit demselben Namen enthält, gelten Verweise auf diesen Namen als simple_name als mehrdeutig.

Das namespace_name-Element, auf das durch global_using_namespace_directive verwiesen wird, wird auf die gleiche Weise aufgelöst wie namespace_or_type_name, auf das durch global_using_alias_directive verwiesen wird. Daher wirken sich global_using_namespace_directives im selben Programm nicht gegenseitig aus und können in beliebiger Reihenfolge geschrieben werden.

Globale using static-Anweisungen

global_using_static_directive importiert die geschachtelten Typen und statischen Member, die direkt in einer Typdeklaration enthalten sind, in das enthaltende Programm, sodass der Bezeichner jedes Members und Typs ohne Qualifikation verwendet werden kann.

global_using_static_directive
    : 'global' 'using' 'static' type_name ';'
    ;

Innerhalb von Memberdeklarationen in einem Programm, das global_using_static_directive enthält, kann direkt auf die zugreifbaren verschachtelten Typen und statischen Member (mit Ausnahme von Erweiterungsmethoden), die direkt in der Deklaration des angegebenen Typs enthalten sind, verwiesen werden.

global_using_static_directive importiert Erweiterungsmethoden nicht direkt als statische Methoden, stellt sie jedoch für den Aufruf der Erweiterungsmethode zur Verfügung.

Ein global_using_static_directive importiert nur Elemente und Typen, die direkt im angegebenen Typ deklariert sind, nicht Elemente und Typen, die in Basisklassen deklariert sind.

Mehrdeutigkeiten zwischen mehreren global_using_namespace_directive-Elementen und global_using_static_directives werden im Abschnitt für global_using_namespace_directive-Elemente (oben) erläutert.

Qualifiziertes Aliasmember §14.8

Es werden Änderungen am Algorithmus vorgenommen, mit dem die Bedeutung von qualified_alias_member ermittelt wird.

Dies ist der relevante Aufzählungspunkt mit vorgeschlagenen Ergänzungen (die fett formatiert sind):

  • Andernfalls beginnt man mit der Namespacedeklaration (§14.3), die unmittelbar das qualifizierte_Alias_Mitglied (falls vorhanden) enthält, und setzt dies mit jeder umschließenden Namespacedeklaration (falls vorhanden) fort. Am Ende wird bei der Kompilierungseinheit, die das qualifizierte_Alias_Mitgliedenthält, der Vorgang abgeschlossen. Die folgenden Schritte werden ausgewertet, bis eine Entität gefunden ist:

    • Wenn die Namespacedeklaration oder Kompilierungseinheit ein using_alias_directive-Element enthält, das N einem Typ zuordnet, oder wenn eine Kompilierungseinheit erreicht wird, enthält das Programm ein global_using_alias_directive-Element, das N einem Typ zuordnet, dann ist qualified_alias_member nicht definiert, und ein Fehler zur Kompilierungszeit tritt auf.
    • Andernfalls, wenn die Namespacedeklaration oder Kompilationseinheit ein extern_alias_directive oder using_alias_directive enthält, das N einem Namespace zuordnet, *oder wenn eine Kompilationseinheit erreicht wird, enthält das Programm ein global_using_alias_directive-Element, das N einem Namespace zuordnet, dann gilt Folgendes:
      • Wenn der mit N verknüpfte Namespace einen Namespace mit dem Namen I enthält und K null ist, bezieht sich die qualified_alias_member auf diesen Namespace.
      • Andernfalls, wenn der Namespace, der N zugeordnet ist, einen nicht generischen Typ namens I enthält und K null ist, dann bezieht sich qualified_alias_member auf diesen Typ.
      • Andernfalls bezieht sich die qualified_alias_member auf diesen Typ, der mit den angegebenen Typargumenten erstellt wurde, wenn der mit N verknüpfte Namespace einen Typ mit dem Namen I enthält, der K Typparameter enthält.
      • Andernfalls ist die qualified_alias_member nicht definiert, und ein Kompilierungszeitfehler tritt auf.