Condividi tramite


Direttiva di Invocazione Globale

Nota

Questo articolo è una specifica di funzionalità. La specifica funge da documento di progettazione per la funzionalità. Include le modifiche specifiche proposte, insieme alle informazioni necessarie durante la progettazione e lo sviluppo della funzionalità. Questi articoli vengono pubblicati fino a quando le modifiche specifiche proposte non vengono completate e incorporate nella specifica ECMA corrente.

Potrebbero verificarsi alcune discrepanze tra la specifica di funzionalità e l'implementazione completata. Tali differenze sono riportate nelle pertinenti note della riunione di progettazione linguistica (LDM).

Altre informazioni sul processo per l'adozione di speclet di funzionalità nello standard del linguaggio C# sono disponibili nell'articolo sulle specifiche di .

Problema del campione: https://github.com/dotnet/csharplang/issues/3428

La sintassi per una direttiva using è estesa con la parola chiave facoltativa global che può precedere la parola chiave using:

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 ';'
    ;
  • I global_using_directivesono consentiti solo a livello di unità di compilazione (non possono essere usati all'interno di una namespace_declaration).
  • L'global_using_directive, se presente, deve precedere qualsiasi using_directives.
  • L'ambito di un global_using_directivesi estende sui namespace_member_declarationdi tutte le unità di compilazione all'interno del programma. L'ambito di una global_using_directive non comprende specificamente altre global_using_directive. Pertanto, peer global_using_directiveo quelli di un'unità di compilazione diversa non influiscono l'uno sull'altro e l'ordine in cui vengono scritti è insignificante. L'ambito di un global_using_directive, in particolare, esclude gli using_directiveche si trovano immediatamente in qualsiasi unità di compilazione del programma.

L'effetto dell'aggiunta di un global_using_directive a un programma può essere considerato come l'effetto dell'aggiunta di un using_directive simile che si risolve nello stesso spazio dei nomi o tipo di destinazione a ogni unità di compilazione del programma. Tuttavia, la destinazione di un global_using_directive viene risolta nel contesto dell'unità di compilazione che lo contiene.

§7.7 Ambiti

Questi sono i punti elenco pertinenti con aggiunte proposte (che sono in grassetto):

  • L'ambito del nome definito da un extern_alias_directive si estende su global_using_directives,using_directives, global_attributes e namespace_member_declarations dell'unità di compilazione o del corpo dello spazio dei nomi che lo contiene immediatamente. Un extern_alias_directive non aggiunge nuovi membri allo spazio di dichiarazione sottostante. In altre parole, un extern_alias_directive non è transitivo, ma influisce solo sull'unità di compilazione o sul corpo dello spazio dei nomi in cui si verifica.
  • L'ambito di un nome definito o importato da un global_using_directive si estende sul global_attributes e namespace_member_declarationdi tutti i compilation_unitnel programma.

nomi di tipo e spazio dei nomi.8

Le modifiche vengono apportate all'algoritmo determinando il significato di un namespace_or_type_name come indicato di seguito.

Questo è il punto elenco pertinente con le aggiunte proposte (che sono in grassetto ):

  • Se il namespace_or_type_name è del formato I o del modulo I<A1, ..., Ak>:
    • Se K è zero e il namespace_or_type_name viene visualizzato all'interno di una dichiarazione di metodo generico (§15.6) e se tale dichiarazione include un parametro di tipo (§15.2.3) con nome I, il namespace_or_type_name fa riferimento a tale parametro di tipo.
    • In caso contrario, se il namespace_or_type_name compare all'interno di una dichiarazione di tipo, per ogni tipo di istanza T (§15.3.2), a partire dal tipo di istanza della dichiarazione di tipo e continuando con il tipo di istanza di ogni dichiarazione di classe o struct che li racchiude (se presente):
      • Se K è zero e la dichiarazione di T include un parametro di tipo con nome I, il namespace_or_type_name fa riferimento a tale parametro di tipo.
      • In caso contrario, se il namespace_or_type_name viene visualizzato all'interno del corpo della dichiarazione di tipo e T o uno dei relativi tipi di base contiene un tipo accessibile annidato con nome I e K parametri di tipo, il namespace_or_type_name fa riferimento a tale tipo costruito con gli argomenti di tipo specificati. Se è presente più di un tipo di questo tipo, viene selezionato il tipo dichiarato all'interno del tipo più derivato. Si noti che i membri non di tipo (costanti, campi, metodi, proprietà, indicizzatori, operatori, costruttori di istanza, distruttori e costruttori statici) e membri di tipo con un numero diverso di parametri di tipo vengono ignorati quando si determina il significato del namespace_or_type_name.
    • Se i passaggi precedenti hanno avuto esito negativo, per ogni spazio dei nomi N, a partire dallo spazio dei nomi in cui si verifica il namespace_or_type_name, continuando con ogni spazio dei nomi contenitore (se presente) e terminando con lo spazio dei nomi globale, i passaggi seguenti vengono valutati fino a quando non viene individuata un'entità:
      • Se K è zero e I è il nome di uno spazio dei nomi in N, allora:
        • Se il percorso in cui si verifica il namespace_or_type_name è racchiuso da una dichiarazione dello spazio dei nomi per N e la dichiarazione dello spazio dei nomi contiene un extern_alias_directive o un using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo, o qualsiasi dichiarazione dello spazio dei nomi per N nel programma contiene una global_using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo, quindi il namespace_or_type_name è ambiguo e si verifica un errore in fase di compilazione.
        • In caso contrario, il namespace_or_type_name fa riferimento allo spazio dei nomi denominato I in N.
      • In caso contrario, se N contiene un tipo accessibile con I nome e parametri di tipo K, allora:
        • Se K è zero e la posizione in cui si verifica il namespace_or_type_name è racchiusa da una dichiarazione dello spazio dei nomi per N e la dichiarazione dello spazio dei nomi contiene un extern_alias_directive o un using_alias_directive che associa il nome I a uno spazio dei nomi o a un tipo, o qualsiasi dichiarazione dello spazio dei nomi per N nel programma contiene una global_using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo, quindi il namespace_or_type_name è ambiguo e si verifica un errore in fase di compilazione.
        • In caso contrario, il namespace_or_type_name fa riferimento al tipo costruito con gli argomenti di tipo specificati.
      • In caso contrario, se il luogo in cui si trova il namespace_or_type_name è racchiuso da una dichiarazione di spazio dei nomi per N:
        • Se K è zero e la dichiarazione dello spazio dei nomi contiene un extern_alias_directive o un using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo importato, o qualsiasi dichiarazione dello spazio dei nomi per N nel programma contiene un global_using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo importato, quindi il namespace_or_type_name fa riferimento a tale spazio dei nomi o tipo.
        • Altrimenti, se gli spazi dei nomi e le relative dichiarazioni di tipo importati dai using_namespace_directivee i using_alias_directivedella dichiarazione dello spazio dei nomi e le dichiarazioni di tipo e gli spazi dei nomi importati dai global_using_namespace_directivee i global_using_static_directivedi qualsiasi dichiarazione dello spazio dei nomi per N nel programma contengono esattamente un solo tipo accessibile con nome I e parametri di tipo K, pertanto il namespace_or_type_name fa riferimento a quel tipo costruito con gli argomenti di tipo specificati.
        • In caso contrario, se gli spazi dei nomi e le dichiarazioni di tipo importati dai using_namespace_directivee using_alias_directivedella dichiarazione dello spazio dei nomi e le dichiarazioni di tipo e gli spazi dei nomi importati dai global_using_namespace_directivee global_using_static_directivedi qualsiasi dichiarazione dello spazio dei nomi per N nel programma contengono più di un tipo accessibile con nome I e parametri di tipo K, quindi il namespace_or_type_name è ambiguo e si verifica un errore.
    • In caso contrario, il namespace_or_type_name non è definito e si verifica un errore in fase di compilazione.

Nomi semplici §12.8.4

Le modifiche vengono apportate alle regole di valutazione simple_name come indicato di seguito.

Questo è il punto elenco pertinente con aggiunte proposte (che sono in grassetto):

  • In caso contrario, per ogni spazio dei nomi N, a partire dallo spazio dei nomi in cui si verifica il simple_name, continuando con ogni spazio dei nomi racchiuso (se presente) e terminando con lo spazio dei nomi globale, i passaggi seguenti vengono valutati fino a quando non viene individuata un'entità:
    • Se K è zero e I è il nome di uno spazio dei nomi in N, allora:
      • Se il percorso in cui si verifica il simple_name è racchiuso da una dichiarazione dello spazio dei nomi per N e la dichiarazione dello spazio dei nomi contiene un extern_alias_directive o un using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo, o qualsiasi dichiarazione dello spazio dei nomi per N nel programma contiene un global_using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo, quindi il simple_name è ambiguo e si verifica un errore in fase di compilazione.
      • In caso contrario, il simple_name fa riferimento allo spazio dei nomi denominato I in N.
    • In caso contrario, se N contiene un tipo accessibile con I nome e parametri di tipo K, allora:
      • Se K è zero e la posizione in cui si verifica il simple_name è racchiusa da una dichiarazione dello spazio dei nomi per N e la dichiarazione dello spazio dei nomi contiene un extern_alias_directive o un using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo, o qualsiasi dichiarazione dello spazio dei nomi per N nel programma contiene una global_using_alias_directive che associa il nome I a uno spazio dei nomi o tipo, quindi il simple_name è ambiguo e si verifica un errore in fase di compilazione.
      • In caso contrario, il namespace_or_type_name fa riferimento al tipo costruito con gli argomenti di tipo specificati.
    • In caso contrario, se la posizione in cui si verifica il simple_name è racchiusa da una dichiarazione dello spazio dei nomi per N:
      • Se K è zero e la dichiarazione dello spazio dei nomi contiene un extern_alias_directive o un using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo importato, o qualsiasi dichiarazione dello spazio dei nomi per N nel programma contiene un global_using_alias_directive che associa il nome I a uno spazio dei nomi o un tipo importato, quindi il simple_name fa riferimento a tale spazio dei nomi o tipo.
      • In caso contrario, se gli spazi dei nomi e le dichiarazioni di tipo importati dai using_namespace_directivee using_static_directivedella dichiarazione dello spazio dei nomi e le dichiarazioni di tipo e gli spazi dei nomi importati dai global_using_namespace_directivee global_using_static_directivedi qualsiasi dichiarazione dello spazio dei nomi per N nel programma contengono esattamente un tipo accessibile o membro statico non di estensione con nome I e K parametri di tipo, il simple_name fa riferimento al tipo o al membro costruito con gli argomenti di tipo specificati.
      • Altrimenti, se gli spazi dei nomi e i tipi importati dal using_namespace_directivedella dichiarazione dello spazio dei nomi e gli spazi dei nomi e le dichiarazioni di tipo importati dai global_using_namespace_directivee global_using_static_directivedi qualsiasi dichiarazione dello spazio dei nomi per N nel programma contengono più di un tipo accessibile o membro statico non di metodo di estensione con il nome I e parametri di tipo K, allora il simple_name è ambiguo e si verifica un errore.

Invocazioni del metodo di estensione §12.8.10.3

Le modifiche vengono apportate all'algoritmo per trovare la migliore type_nameC come indicato di seguito. Questo è la voce elenco pertinente con le aggiunte proposte (che sono in **grassetto**):

  • A partire dalla dichiarazione dello spazio dei nomi contenitore più vicina, continuando con ogni dichiarazione dello spazio dei nomi contenitore e terminando con l'unità di compilazione contenitore, vengono eseguiti tentativi successivi di trovare un set candidato di metodi di estensione:
    • Se l'unità di compilazione o dello spazio dei nomi specificata contiene direttamente dichiarazioni di tipo non generico Ci con metodi di estensione idonei Mj, il set di tali metodi di estensione è il set candidato.
    • Se i tipi Ci importati da using_static_declarations e dichiarati direttamente nei namespace importati da using_namespace_directivenel namespace o nell'unità di compilazione specificata e, se viene raggiunta l'unità di compilazione contenitore, importati da global_using_static_declarations e dichiarati direttamente nei namespace importati da global_using_namespace_directivenel programma contengono direttamente metodi di estensione idonei Mj, allora l'insieme di tali metodi di estensione costituisce l'insieme candidato.

Unità di compilazione §14.2

Un compilation_unit definisce la struttura complessiva di un file di origine. Un'unità di compilazione è costituita da zero o più global_using_directiveseguite da zero o più using_directiveseguite da zero o più global_attributes seguite da zero o più namespace_member_declarations.

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

Un programma C# è costituito da una o più unità di compilazione, ognuna contenuta in un file di origine separato. Quando un programma C# viene compilato, tutte le unità di compilazione vengono elaborate insieme. Pertanto, le unità di compilazione possono dipendere l'una dall'altra, possibilmente in modo circolare.

I global_using_directivedi un'unità di compilazione influiscono sui global_attributes e namespace_member_declarationdi tutte le unità di compilazione del programma.

Alias esterni §14.4

L'ambito di un extern_alias_directive si estende sui global_using_directive,using_directive, global_attributes e namespace_member_declarationdel relativo corpo immediatamente contenente l'unità di compilazione o il corpo dello spazio dei nomi.

Uso delle direttive alias §14.5.2

L'ordine in cui i using_alias_directivesono scritti non ha alcun significato e la risoluzione del namespace_or_type_name a cui fa riferimento un using_alias_directive non è influenzata dal using_alias_directive stesso o da altri using_directivenel corpo dell'unità di compilazione o dello spazio dei nomi che contiene immediatamente, e, se il using_alias_directive è immediatamente contenuto in un'unità di compilazione, non è interessato dal global_using_directivenel programma. In altre parole, il namespace_or_type_name di un using_alias_directive viene risolto come se il corpo dell'unità di compilazione o dello spazio dei nomi immediatamente contenuto non avesse using_directivee, se il using_alias_directive è direttamente contenuto in un'unità di compilazione, il programma non avesse global_using_directive. Un using_alias_directive può tuttavia essere influenzato da extern_alias_directives nell'unità di compilazione o nel corpo dello spazio dei nomi che lo contiene immediatamente.

Direttive globali using alias

Un global_using_alias_directive introduce un identificatore che funge da alias per uno spazio dei nomi o un tipo all'interno del programma.

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

All'interno delle dichiarazioni dei membri di un'unità di compilazione di un programma che contiene un global_using_alias_directive, l'identificatore introdotto dall' global_using_alias_directive può essere utilizzato per fare riferimento allo spazio dei nomi o al tipo specificato.

L'identificatore di un global_using_alias_directive deve essere univoco all'interno dello spazio di dichiarazione di qualsiasi unità di compilazione di un programma contenente l'global_using_alias_directive.

Analogamente ai membri regolari, i nomi introdotti da global_using_alias_directives sono nascosti da membri con nomi simili negli scopi annidati.

L'ordine in cui i global_using_alias_directivesono scritti non ha alcun significato e la risoluzione dei namespace_or_type_name a cui fa riferimento un global_using_alias_directive non è influenzata dal global_using_alias_directive stesso o da altri global_using_directiveo using_directives nel programma. In altre parole, il namespace_or_type_name di un global_using_alias_directive viene risolto come se l'unità di compilazione contenente immediatamente non avesse using_directives e l'intero programma contenitore non aveva global_using_directives. Un global_using_alias_directive può tuttavia essere influenzato da extern_alias_directivenell'unità di compilazione che lo contiene immediatamente.

Un global_using_alias_directive può creare un alias per qualsiasi namespace o tipo.

L'accesso a uno spazio dei nomi o un tipo tramite un alias restituisce esattamente lo stesso risultato dell'accesso allo spazio dei nomi o al tipo tramite il nome dichiarato.

L'uso di alias può denominare un tipo costruito chiuso, ma non può denominare una dichiarazione di tipo generico non associato senza fornire argomenti di tipo.

Direttive dello spazio dei nomi Global Using

Un global_using_namespace_directive importa i tipi contenuti in uno spazio dei nomi nel programma, consentendo l'identificatore di ogni tipo da poter essere utilizzato senza qualificazione.

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

All'interno delle dichiarazioni dei membri in un programma che contiene un global_using_namespace_directive, è possibile fare riferimento direttamente ai tipi contenuti nel namespace specificato.

Un global_using_namespace_directive importa i tipi contenuti nello spazio dei nomi specificato, ma in particolare non importa spazi dei nomi annidati.

A differenza di un global_using_alias_directive, un global_using_namespace_directive può importare i tipi i cui identificatori sono già definiti all'interno di un'unità di compilazione del programma. In effetti, in una determinata unità di compilazione, i nomi importati da qualsiasi global_using_namespace_directive nel programma sono nascosti da membri denominati in modo analogo nell'unità di compilazione.

Quando più di uno spazio dei nomi o un tipo importato da global_using_namespace_directives o global_using_static_directivenello stesso programma contengono tipi con lo stesso nome, i riferimenti a tale nome come type_name sono considerati ambigui.

Inoltre, quando più di uno spazio dei nomi o un tipo importato da global_using_namespace_directiveo global_using_static_directives nello stesso programma contengono tipi o membri con lo stesso nome, i riferimenti a tale nome come simple_name vengono considerati ambigui.

Il namespace_name a cui fa riferimento un global_using_namespace_directive viene risolto nello stesso modo in cui il namespace_or_type_name a cui fa riferimento un global_using_alias_directive. Pertanto, global_using_namespace_directivenello stesso programma non influiscono tra di loro e possono essere scritti in qualsiasi ordine.

Direttive statiche global using

Un global_using_static_directive importa i tipi annidati e i membri statici contenuti direttamente in una dichiarazione del tipo nel programma contenitore, consentendo l'uso degli identificatori di ciascun membro e tipo senza qualificatori.

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

All'interno di dichiarazioni membro in un programma che contiene un global_using_static_directive, è possibile fare riferimento direttamente ai tipi annidati accessibili e ai membri statici (ad eccezione dei metodi di estensione) contenuti direttamente nella dichiarazione del tipo specificato.

Un global_using_static_directive in particolare non importa i metodi di estensione direttamente come metodi statici, ma li rende disponibili per la chiamata al metodo di estensione.

Un global_using_static_directive importa solo membri e tipi dichiarati direttamente nel tipo specificato, non membri e tipi dichiarati nelle classi di base.

Le ambiguità tra più global_using_namespace_directivee global_using_static_directives sono descritte nella sezione relativa ai global_using_namespace_directive(sopra).

Membro alias qualificato §14.8

Le modifiche vengono apportate all'algoritmo determinando il significato di un qualified_alias_member come indicato di seguito.

Questo è il punto elenco rilevante con aggiunte proposte (che sono in grassetto):

  • In caso contrario, a partire dalla dichiarazione dello spazio dei nomi (§14.3) immediatamente contenente il qualified_alias_member (se presente), continuando con ogni dichiarazione dello spazio dei nomi racchiusa (se presente) e terminando con l'unità di compilazione contenente il qualified_alias_member, i passaggi seguenti vengono valutati fino a quando non si trova un'entità:

    • Se la dichiarazione dello spazio dei nomi o l'unità di compilazione contiene un using_alias_directive che associa N a un tipo, o, quando viene raggiunta un'unità di compilazione, il programma contiene un global_using_alias_directive che associa N a un tipo, il qualified_alias_member non è definito e si verifica un errore in fase di compilazione.
    • In caso contrario, se la dichiarazione dello spazio dei nomi o l'unità di compilazione contiene un extern_alias_directive o un using_alias_directive che associa N a uno spazio dei nomi, *o, quando viene raggiunta un'unità di compilazione, il programma contiene un global_using_alias_directive che associa N a uno spazio dei nomi, quindi:
      • Se lo spazio dei nomi associato a N contiene uno spazio dei nomi denominato I e K è zero, il qualified_alias_member fa riferimento a tale spazio dei nomi.
      • In caso contrario, se lo spazio dei nomi associato a N contiene un tipo non generico denominato I e K è zero, il qualified_alias_member fa riferimento a tale tipo.
      • In caso contrario, se lo spazio dei nomi associato a N contiene un tipo denominato I con parametri di tipo K, il qualified_alias_member fa riferimento a quel tipo costruito con gli argomenti di tipo specificati.
      • In caso contrario, il qualified_alias_member non è definito e si verifica un errore in fase di compilazione.