Dela via


Globalt användningsdirektiv

Not

Den här artikeln är en funktionsspecifikation. Specifikationen fungerar som designdokument för funktionen. Den innehåller föreslagna specifikationsändringar, tillsammans med information som behövs under utformningen och utvecklingen av funktionen. Dessa artiklar publiceras tills de föreslagna specifikationsändringarna har slutförts och införlivats i den aktuella ECMA-specifikationen.

Det kan finnas vissa skillnader mellan funktionsspecifikationen och den slutförda implementeringen. Dessa skillnader fångas i de relevanta anteckningarna från Language Design Meeting (LDM) .

Du kan läsa mer om processen för att införa funktionsspecifikationer i C#-språkstandarden i artikeln om specifikationerna.

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

Syntaxen för ett användningsdirektiv utökas med ett valfritt global nyckelord som kan föregå nyckelordet 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 ';'
    ;
  • global_using_directivetillåts endast på kompileringsenhetsnivå (kan inte användas i en namespace_declaration).
  • Om det finns några global_using_directivemåste de föregå alla using_directive.
  • Omfånget för en global_using_directivesträcker sig över namespace_member_declarationför alla kompileringsenheter inom programmet. Omfånget för en global_using_directive inkluderar inte andra global_using_directives. Därför påverkar peer-global_using_directiveeller de från en annan kompileringsenhet inte varandra, och ordningen i vilken de skrivs är obetydlig. Omfånget för en global_using_directive inkluderar specifikt inte using_directivesom finns direkt i någon programenhet av programmet.

Effekten av att lägga till en global_using_directive i ett program kan ses som effekten av att lägga till en liknande using_directive som matchar samma målnamnområde eller typ till varje kompileringsenhet i programmet. Målet för en global_using_directive löses dock i samband med kompileringsenheten som innehåller den.

§7.7 Omfattning

Det här är relevanta punkter med föreslagna tillägg (som i fetstil):

  • Namnomfånget som definieras av en extern_alias_directive sträcker sig över global_using_directives,using_directives, global_attributes och namespace_member_declarationav dess omedelbart innehållande kompileringsenhet eller namnområdestext. En extern_alias_directive bidrar inte med några nya element till det underliggande deklarationsutrymmet. Med andra ord är en extern_alias_directive inte transitiv, utan påverkar snarare bara kompileringsenheten eller namnområdestexten där den inträffar.
  • Omfånget för ett namn som definierats eller importerats av en global_using_directive sträcker sig över global_attributes och namespace_member_declarationför alla compilation_uniti programmet.

§7.8 Namnrymd och typnamn

Ändringar görs i algoritmen som bestämmer innebörden av en namespace_or_type_name enligt följande.

Det här är den relevanta punktpunkten med föreslagna tillägg (som i fetstil):

  • Om namespace_or_type_name är i formen I eller i formen I<A1, ..., Ak>:
    • Om K är noll och namespace_or_type_name visas i en allmän metoddeklaration (§15.6) och om den deklarationen innehåller en typparameter (§15.2.3) med namnet I, refererar namespace_or_type_name till den typparametern.
    • Annars, om namespace_or_type_name visas inom en typdeklaration, så för varje instanstyp T (§15.3.2), börjar med instanstypen av den typdeklarationen och fortsätter med instanstypen för varje omslutande klass eller structdeklaration (om någon):
      • Om K är noll och deklarationen av T innehåller en typparameter med namnet Irefererar namespace_or_type_name till den typparametern.
      • Annars, om namespace_or_type_name visas i brödtexten i typdeklarationen, och T eller någon av dess bastyper innehåller en kapslad tillgänglig typ med namn I och K typparametrar, refererar namespace_or_type_name till den typen som konstruerats med de angivna typargumenten. Om det finns fler än en sådan typ väljs den typ som deklarerats inom den mer härledda typen. Observera att icke-typmedlemmar (konstanter, fält, metoder, egenskaper, indexerare, operatorer, instanskonstruktorer, destructors och statiska konstruktorer) och typmedlemmar med ett annat antal typparametrar ignoreras när innebörden av namespace_or_type_namebestäms.
    • Om föregående steg misslyckades utvärderas följande steg tills en entitet finns för varje namnområde N, med början i namnområdet där namespace_or_type_name inträffar, fortsätter med varje omslutande namnområde (om det finns) och slutar med det globala namnområdet:
      • Om K är noll och I är namnet på ett namnområde i N, så:
        • Om platsen där namespace_or_type_name inträffar omges av en namnområdesdeklaration för N och namnområdesdeklarationen innehåller en extern_alias_directive eller using_alias_directive som associerar namnet I med ett namnområde eller en typ, eller någon namnområdesdeklaration för N i programmet innehåller en global_using_alias_directive som associerar namnet I med ett namnområde eller en typ, är namespace_or_type_name tvetydigt och ett kompileringsfel inträffar.
        • Annars refererar namespace_or_type_name till namnområdet med namnet I i N.
      • Annars, om N innehåller en tillgänglig typ med namn I och K typparametrar, så:
        • Om K är noll och platsen där namespace_or_type_name inträffar omges av en namnområdesdeklaration för N och namnområdesdeklarationen innehåller en extern_alias_directive eller using_alias_directive som associerar namnet I med ett namnområde eller typ, innehåller eller någon namnområdesdeklaration för N i programmet en global_using_alias_directive som associerar namnet I med ett namnområde eller en typ, sedan namespace_or_type_name är tvetydig och ett kompileringsfel inträffar.
        • Annars refererar namespace_or_type_name till den typ som skapats med de angivna typargumenten.
      • Annars, om platsen där namespace_or_type_name inträffar omges av en namnrymddeklaration för N:
        • Om K är noll och namnområdesdeklarationen innehåller en extern_alias_directive eller using_alias_directive som associerar namnet I med ett importerat namnområde eller typ, innehåller eller någon namnområdesdeklaration för N i programmet en global_using_alias_directive som associerar namnet I med ett importerat namnområde eller typ. refererar namespace_or_type_name till namnområdet eller typen.
        • Om namnrymderna och typdeklarationerna som importerats av using_namespace_directives och using_alias_directivei namnområdesdeklarationen samt namnrymderna och typdeklarationerna som importerats av global_using_namespace_directives och global_using_static_directivei någon namnområdesdeklaration för N i programmet innehåller exakt en tillgänglig typ med namn I och K typparametrar, refererar namespace_or_type_name till den typen skapad med de angivna typargumenten.
        • Om namnområdena och typdeklarationerna som importeras av using_namespace_directives och using_alias_directives i namnområdesdeklarationen och namnområdena och typdeklarationerna som importeras av global_using_namespace_directives och global_using_static_directives i deklarationen för något namnområde för N i programmet innehåller fler än en tillgänglig typ med namn I och K typparametrar, då är namespace_or_type_name tvetydig och ett fel inträffar.
    • Annars är namespace_or_type_name odefinierat och ett kompileringsfel inträffar.

Enkla namn §12.8.4

Ändringar görs i simple_name utvärderingsregler på följande sätt.

Det här är den relevanta punktpunkten med föreslagna tillägg (som i fetstil):

  • I annat fall utvärderas följande steg tills en entitet finns för varje namnområde N, från och med namnområdet där simple_name inträffar, fortsätter med varje omslutande namnområde (om det finns) och slutar med det globala namnområdet:
    • Om K är noll och I är namnet på ett namnområde i N, så:
      • Om platsen där simple_name inträffar omges av en namnområdesdeklaration för N och namnområdesdeklarationen innehåller en extern_alias_directive eller using_alias_directive som associerar namnet I med ett namnområde eller en typ, eller någon namnområdesdeklaration för N i programmet innehåller en global_using_alias_directive som associerar namnet I med ett namnområde eller en typ, är simple_name tvetydigt och ett kompileringsfel inträffar.
      • Annars refererar simple_name till namnområdet med namnet I i N.
    • Annars, om N innehåller en tillgänglig typ med namn I och K typparametrar, så:
      • Om K är noll och platsen där simple_name inträffar omges av en namnområdesdeklaration för N och namnområdesdeklarationen innehåller en extern_alias_directive eller using_alias_directive som associerar namnet I med ett namnområde eller typ, eller en namnområdesdeklaration för N i programmet innehåller en global_using_alias_directive som associerar namnet I med ett namnområde eller typ, är simple_name tvetydig och ett kompileringsfel inträffar.
      • Annars refererar namespace_or_type_name till den typ som skapats med de angivna typargumenten.
    • Annars, om platsen där simple_name är placerad är omsluten av en namnområdesdeklaration för N:
      • Om K är noll och namnområdesdeklarationen innehåller en extern_alias_directive eller using_alias_directive som associerar namnet I med ett importerat namnområde eller typ, innehåller eller någon namnområdesdeklaration för N i programmet en global_using_alias_directive som associerar namnet I med ett importerat namnområde eller typ. refererar simple_name till namnområdet eller typen.
      • Om namnrymderna och typdeklarationerna som importerats av using_namespace_directiveoch using_static_directivei namnområdesdeklarationen och namnrymderna och typdeklarationerna som importerats av global_using_namespace_directiveoch global_using_static_directivei någon namnområdesdeklaration för N i programmet innehåller exakt en tillgänglig typ eller icke-utbyggbar statisk medlem med namnet I och K typparametrar, syftar simple_name på den typen eller medlemmen som är skapade med de specificerade typargumenten.
      • Om namnrymderna och typerna som importerats av using_namespace_directivei namnområdesdeklarationen och namnrymderna och typdeklarationerna som importerats av global_using_namespace_directiveoch global_using_static_directivei någon namnområdesdeklaration för N i programmet innehåller mer än en tillgänglig typ eller statisk medlem utan tilläggsmetod med namnet I och K typparametrar, då är simple_name tvetydig och ett fel inträffar.

Tilläggsmetodanrop §12.8.10.3

Ändringar görs i algoritmen för att hitta den bästa type_nameC enligt följande. Det här är den relevanta punkten med föreslagna tillägg (i fetstil ):

  • Från och med den närmaste omslutande namnområdesdeklarationen, fortsätter med varje omslutande namnområdesdeklaration och slutar med den innehållande kompileringsenheten, görs efterföljande försök att hitta en kandidatuppsättning med tilläggsmetoder:
    • Om det angivna namnområdet eller kompileringsenheten direkt innehåller icke-generiska typdeklarationer Ci med berättigade tilläggsmetoder Mjär uppsättningen med dessa tilläggsmetoder kandidatuppsättningen.
    • Om typer Ci importeras av using_static_declarations och direkt deklareras i namnområden som importerats av using_namespace_directivei det angivna namnområdet eller kompileringsenheten . Om den innehållande kompileringsenheten nås, importeras de av global_using_static_declarations och deklareras direkt i namnområden som importeras av global_using_namespace_directivei programmet, som direkt innehåller giltiga extension methods Mj, då är mängden av dessa extension methods kandidatuppsättningen.

Kompileringsenheter §14.2

En compilation_unit definierar den övergripande strukturen för en källfil. En kompileringsenhet består av noll eller fler global_using_directive, följt av noll eller fler using_directive, följt av noll eller fler global_attributes, följt av noll eller fler namespace_member_declaration.

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

Ett C#-program består av en eller flera kompileringsenheter som var och en finns i en separat källfil. När ett C#-program kompileras bearbetas alla kompileringsenheter tillsammans. Kompileringsenheter kan därför vara beroende av varandra, möjligen på ett cirkulärt sätt.

global_using_directivei en kompileringsenhet påverkar global_attributes och namespace_member_declarationi alla kompileringsenheter i programmet.

Externa alias §14.4

Omfånget för en extern_alias_directive sträcker sig över global_using_directives,using_directives, global_attributes och namespace_member_declarations av den kompileringsenhet eller namnområdeskropp som omedelbart inkluderar den.

Använda aliasdirektiv §14.5.2

Den ordning i vilken using_alias_directives skrivs har ingen betydelse, och upplösningen av namespace_or_type_name som refereras av en using_alias_directive påverkas inte av själva using_alias_directive eller av andra using_directives i den omedelbart innehållande kompileringsenheten eller namnområdestexten. och, om using_alias_directive omedelbart finns i en kompileringsenhet, inte påverkas av global_using_directivei programmet. Med andra ord utreds namespace_or_type_name av en using_alias_directive som om den omedelbart innehållande kompileringsenheten eller namnområdeskroppen inte hade några using_directiveoch, om using_alias_directive omedelbart finns i en kompileringsenhet, som om programmet inte hade några global_using_directive. En using_alias_directive kan dock påverkas av extern_alias_directivei den närmast innehållande kompileringsenheten eller namnområdekroppen.

Globala aliasdirektiv för användning

En global_using_alias_directive introducerar en identifierare som fungerar som ett alias för ett namnområde eller en typ i programmet.

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

I medlemsdeklarationer i en kompileringsenhet i ett program som innehåller en global_using_alias_directivekan identifieraren som introducerades av global_using_alias_directive användas för att referera till det angivna namnområdet eller typen.

identifierare för en global_using_alias_directive måste vara unik inom deklarationsutrymmet för en kompileringsenhet i ett program som innehåller global_using_alias_directive.

Precis som vanliga medlemmar, döljs namn som introduceras av global_using_alias_directives av medlemmar med liknande namn i inbäddade omfång.

Den ordning i vilken global_using_alias_directives skrivs har ingen betydelse, och lösningen av namespace_or_type_name som refereras av en global_using_alias_directive påverkas inte av själva global_using_alias_directive eller av andra global_using_directives eller using_directivei programmet. Med andra ord hanteras namespace_or_type_name i en global_using_alias_directive som om den omedelbart innehållande kompileringsenheten saknade using_directiveoch att hela det innehållande programmet saknade global_using_directive. En global_using_alias_directive kan dock påverkas av extern_alias_directivei den närmast överordnade kompileringsenheten.

En global_using_alias_directive kan skapa ett alias för valfritt namnområde eller typ.

Åtkomst till ett namnområde eller en typ via ett alias ger exakt samma resultat som åtkomst till namnområdet eller typ via dess deklarerade namn.

Om du använder alias kan du namnge en sluten konstruktionstyp, men det går inte att namnge en obundet allmän typdeklaration utan att ange typargument.

Global användning av namnområdesdirektiv

En global_using_namespace_directive importerar de typer som finns i ett namnområde till programmet, vilket gör att identifieraren för varje typ kan användas utan kvalificering.

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

I medlemsdeklarationer i ett program som innehåller en global_using_namespace_directivekan de typer som finns i det angivna namnområdet refereras direkt.

En global_using_namespace_directive importerar de typer som finns i det angivna namnområdet, men importerar inte kapslade namnområden.

Till skillnad från en global_using_alias_directivekan en global_using_namespace_directive importera typer vars identifierare redan har definierats i en kompileringsenhet i programmet. I själva verket döljs i en viss kompileringsenhet namn som importeras av alla global_using_namespace_directive i programmet av medlemmar med samma namn i kompileringsenheten.

Om fler än ett namnområde eller en typ som importerats av global_using_namespace_directives eller global_using_static_directives i samma program innehåller typer med samma namn, anses referenser till det namnet som en type_name tvetydiga.

Om mer än ett namnområde eller en typ som importerats av global_using_namespace_directives eller global_using_static_directives i samma program innehåller typer eller medlemmar med samma namn anses referenser till det namnet som en simple_name dessutom vara tvetydiga.

Den namespace_name som refereras av en global_using_namespace_directive matchas på samma sätt som den namespace_or_type_name som refereras av en global_using_alias_directive. Därför påverkar global_using_namespace_directivei samma program inte varandra och kan skrivas i valfri ordning.

Global användning av statiska direktiv

En global_using_static_directive importerar kapslade typer och statiska medlemmar som finns direkt i en typdeklaration till det innehållande programmet, vilket gör att identifieraren för varje medlem och typ kan användas utan kvalificering.

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

I medlemsdeklarationer i ett program som innehåller en global_using_static_directivekan tillgängliga kapslade typer och statiska medlemmar (förutom tilläggsmetoder) som finns direkt i deklarationen av den angivna typen refereras direkt.

En global_using_static_directive importerar inte tilläggsmetoder som statiska metoder direkt, utan gör dem tillgängliga för anrop av tilläggsmetod.

En global_using_static_directive importerar endast medlemmar och typer som deklarerats direkt i den angivna typen, inte medlemmar och typer som deklarerats i basklasser.

Tvetydigheter mellan flera global_using_namespace_directiveoch global_using_static_directives beskrivs i avsnittet för global_using_namespace_directives (ovan).

Kvalificerad aliasmedlem §14.8

Ändringar görs i algoritmen som bestämmer innebörden av en qualified_alias_member enligt följande.

Det här är den relevanta punktpunkten med föreslagna tillägg (som i fetstil):

  • Annars, från och med namnområdesdeklarationen (§14.3) som omedelbart innehåller qualified_alias_member (om sådan finns), fortsätter med varje omslutande namnområdesdeklaration (om sådan finns) och slutar med kompileringsenheten som innehåller qualified_alias_member, utvärderas följande steg tills en entitet finns:

    • Om namnområdesdeklarationen eller kompileringsenheten innehåller en using_alias_directive som associerar N med en typ, eller, när en kompileringsenhet nås, innehåller programmet en global_using_alias_directive som associerar N med en typ,qualified_alias_member är odefinierat och ett kompileringsfel inträffar.
    • Annars, om namnområdesdeklarationen eller kompileringsenheten innehåller en extern_alias_directive eller using_alias_directive som associerar N med ett namnområde, *eller, när en kompileringsenhet nås, innehåller programmet en global_using_alias_directive som associerar N med ett namnområde, sedan:
      • Om namnområdet som är associerat med N innehåller ett namnområde med namnet I och K är noll refererar qualified_alias_member till namnområdet.
      • Om namnområdet som är associerat med N innehåller en icke-generisk typ med namnet I och K är noll refererar qualified_alias_member till den typen.
      • Annars, om namnområdet som är associerat med N innehåller en typ med namnet I som har K typparametrar, refererar qualified_alias_member till den typen som skapats med de angivna typargumenten.
      • Annars är qualified_alias_member odefinierat och ett kompileringsfel inträffar.