Condividi tramite


Spazi dei nomi con ambito di file

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. Quelle differenze vengono acquisite nelle note pertinenti della riunione di progettazione del linguaggio (LDM) .

Puoi trovare ulteriori informazioni sul processo di adozione degli speclet delle funzionalità nello standard del linguaggio C# nell'articolo sulle specifiche di .

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

Sommario

Gli spazi dei nomi a livello di file usano un formato meno verboso nel caso tipico di file contenenti un solo spazio dei nomi. Il formato dello spazio dei nomi con ambito file è namespace X.Y.Z; (si noti il punto e virgola e l'assenza di parentesi graffe). In questo modo è possibile usare file simili ai seguenti:

namespace X.Y.Z;

using System;

class X
{
}

La semantica è che l'uso del modulo namespace X.Y.Z; equivale a scrivere namespace X.Y.Z { ... } in cui il resto del file che segue lo spazio dei nomi con ambito file si trova nella sezione ... di una dichiarazione dello spazio dei nomi standard.

Motivazione

L'analisi dell'ecosistema C# mostra che circa 99,7% file sono tutti uno di questi formati:

namespace X.Y.Z
{
    // usings

    // types
}

o

// usings

namespace X.Y.Z
{
    // types
}

Tuttavia, entrambe queste forme costringono l'utente a rientrare la maggior parte del codice e aggiungere una certa quantità di formalità per ciò che è effettivamente un concetto basilare. Ciò influisce sulla chiarezza, utilizza lo spazio orizzontale e verticale e spesso non è soddisfacente per gli utenti abituati a C# e provenienti da altri linguaggi (che qui in genere richiedono meno cerimonia).

L'obiettivo principale della funzionalità è quindi soddisfare le esigenze della maggior parte dell'ecosistema con meno boilerplate inutili.

Progettazione dettagliata

Questa proposta assume la forma di una modifica alle unità di compilazione esistenti (sezione§14.2) delle specifiche.

Differenza

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

Un compilation_unit definisce la struttura complessiva di un file di origine. Un'unità di compilazione è costituita da zero o più using_directiveseguite da zero o più global_attributes seguite da un compilation_unit_body. Un corpo_dell'unità_di_compilazione può essere una dichiarazione_del_namespace_a_livello_di_file o zero o più istruzionie dichiarazioni_di_membri_del_namespace.

compilation_unit
~~    : extern_alias_directive* using_directive* global_attributes? namespace_member_declaration*~~
    : extern_alias_directive* using_directive* global_attributes? compilation_unit_body
    ;

compilation_unit_body
    : statement* namespace_member_declaration*
    | file_scoped_namespace_declaration
    ;

... inalterato...

Un file_scoped_namespace_declaration contribuirà ai membri corrispondenti al namespace_declaration a cui è semanticamente equivalente. Per altri dettagli, vedere ( dichiarazioni dello spazio dei nomi).

Dichiarazioni dello spazio dei nomi

Un namespace_declaration è costituito dalla parola chiave namespace, seguita da un nome e un corpo dello spazio dei nomi, seguiti facoltativamente da un punto e virgola. Un file_scoped_namespace_declaration è costituito dalla parola chiave namespace, seguita da un nome dello spazio dei nomi, un punto e virgola e un elenco facoltativo di extern_alias_directives, using_directives e type_declarations.

namespace_declaration
    : 'namespace' qualified_identifier namespace_body ';'?
    ;
    
file_scoped_namespace_declaration
    : 'namespace' qualified_identifier ';' extern_alias_directive* using_directive* type_declaration*
    ;

... unchanged ...

... inalterato...

le due dichiarazioni dello spazio dei nomi precedenti contribuiscono allo stesso spazio di dichiarazione, in questo caso dichiarando due classi con i nomi completi N1.N2.A e N1.N2.B. Poiché le due dichiarazioni contribuiscono allo stesso spazio di dichiarazione, sarebbe stato un errore se ognuna contenga una dichiarazione di un membro con lo stesso nome.

Un file_scoped_namespace_declaration consente la scrittura di una dichiarazione dello spazio dei nomi senza il blocco { ... }. Per esempio:

extern alias A;
namespace Name;
using B;
class C
{
}

è semanticamente equivalente a

extern alias A;
namespace Name
{
    using B;
    class C
    {
    }
}

In particolare, un file_scoped_namespace_declaration viene considerato uguale a un namespace_declaration nella stessa posizione del compilation_unit con lo stesso qualified_identifier. Gli extern_alias_directive, i using_directivee i type_declarationdi quel file_scoped_namespace_declaration agiscono come se fossero dichiarati nello stesso ordine all'interno del namespace_body di quella namespace_declaration.

Un file di origine non può contenere sia un file_scoped_namespace_declaration che un namespace_declaration. Un file sorgente non può contenere più dichiarazioni file_scoped_namespace_declaration. Un compilation_unit non può contenere sia un file_scoped_namespace_declaration che istruzioni di primo livello. type_declarationnon può precedere un file_scoped_namespace_declaration.

Alias esterni

... inalterato...