Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
14.1 Allmänt
C#-program ordnas med hjälp av namnområden. Namnrymder används både som ett "internt" organisationssystem för ett program och som ett "externt" organisationssystem – ett sätt att presentera programelement som exponeras för andra program.
Användning av direktiv (§14.5) tillhandahålls för att underlätta användningen av namnområden.
14.2 Kompileringsenheter
En compilation_unit består av noll eller fler extern_alias_directiveföljt av noll eller fler using_directiveföljt av noll eller en global_attributes följt av noll eller fler namespace_member_declarations. Compilation_unit definierar den övergripande strukturen för indata.
compilation_unit
    : extern_alias_directive* using_directive* global_attributes?
      namespace_member_declaration*
    ;
Ett C#-program består av en eller flera kompileringsenheter. 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.
Extern_alias_directivei en kompileringsenhet påverkar using_directives, global_attributes och namespace_member_declarationi den kompileringsenheten, men påverkar inte andra kompileringsenheter.
Using_directiveför en kompileringsenhet påverkar global_attributes och namespace_member_declarationi den kompileringsenheten, men påverkar inte andra kompileringsenheter.
Den global_attributes (§23.3) av en kompileringsenhet tillåter specifikation av attribut för målsammansättningen och modulen. Sammansättningar och moduler fungerar som fysiska containrar för typer. En sammansättning kan bestå av flera fysiskt separata moduler.
Namespace_member_declaration förvarje kompileringsenhet i ett program bidrar medlemmar till ett enda deklarationsutrymme som kallas globalt namnområde.
Example:
// File A.cs: class A {} // File B.cs: class B {}De två kompileringsenheterna bidrar till det enskilda globala namnområdet, i det här fallet deklarerar de två klasserna med de fullständigt kvalificerade namnen
AochB. Eftersom de två kompileringsenheterna bidrar till samma deklarationsutrymme skulle det ha varit ett fel om var och en innehöll en deklaration av en medlem med samma namn.slutexempel
14.3 Namnområdesdeklarationer
En namespace_declaration består av nyckelordets namnområde följt av ett namnområdesnamn och en brödtext, eventuellt följt av ett semikolon.
namespace_declaration
    : 'namespace' qualified_identifier namespace_body ';'?
    ;
qualified_identifier
    : identifier ('.' identifier)*
    ;
namespace_body
    : '{' extern_alias_directive* using_directive*
      namespace_member_declaration* '}'
    ;
En namespace_declaration kan inträffa som en deklaration på toppnivå i en compilation_unit eller som en medlemsdeklaration inom en annan namespace_declaration. När en namespace_declaration inträffar som en deklaration på den översta nivån i en compilation_unit blir namnområdet medlem i det globala namnområdet. När en namespace_declaration inträffar inom en annan namespace_declaration blir det inre namnområdet medlem i det yttre namnområdet. I båda fallen ska namnet på ett namnområde vara unikt inom det innehållande namnområdet.
Namnområden är implicita public och deklarationen av ett namnområde kan inte innehålla några åtkomstmodifierare.
Inom en namespace_body importerar den valfria using_directivenamnen på andra namnområden, typer och medlemmar, så att de kan refereras direkt i stället för via kvalificerade namn. Det valfria namespace_member_declarations bidrar medlemmar till namnområdets deklarationsutrymme. Observera att alla using_directiveska visas före eventuella medlemsdeklarationer.
              Qualified_identifier för en namespace_declaration kan vara en enda identifierare eller en sekvens med identifierare avgränsade med "." token. Det senare formuläret tillåter ett program att definiera ett kapslat namnområde utan att lexikalt kapsla flera namnområdesdeklarationer.
Example:
namespace N1.N2 { class A {} class B {} }är semantiskt likvärdigt med
namespace N1 { namespace N2 { class A {} class B {} } }slutexempel
Namnområden är öppna och två namnområdesdeklarationer med samma fullständigt kvalificerade namn (§7.8.3) bidrar till samma deklarationsutrymme (§7.3).
Exempel: I följande kod
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }de två namnområdesdeklarationerna ovan bidrar till samma deklarationsutrymme, i det här fallet deklarera två klasser med de fullständigt kvalificerade namnen
N1.N2.AochN1.N2.B. Eftersom de två deklarationerna bidrar till samma deklarationsutrymme skulle det ha varit ett fel om var och en innehöll en deklaration av en medlem med samma namn.slutexempel
14.4 Externa aliasdirektiv
En extern_alias_directive introducerar en identifierare som fungerar som ett alias för ett namnområde. Specifikationen för det aliaserade namnområdet är externt för programmets källkod och gäller även för kapslade namnområden i det aliaserade namnområdet.
extern_alias_directive
    : 'extern' 'alias' identifier ';'
    ;
Omfånget för en extern_alias_directive sträcker sig över using_directives, global_attributes och namespace_member_declarationför dess omedelbart innehållande compilation_unit eller namespace_body.
I en kompileringsenhet eller namnområdestext som innehåller en extern_alias_directive kan identifieraren som introducerades av extern_alias_directive användas för att referera till det aliaserade namnområdet. Det är ett kompileringsfel för att identifieraren ska vara ordet global.
Aliaset som introduceras av en extern_alias_directive liknar det alias som introducerades av en using_alias_directive. Se §14.5.2 för mer detaljerad diskussion om extern_alias_directives och using_alias_directives.
              alias är ett kontextuellt nyckelord (§6.4.4) och har endast särskild betydelse när det omedelbart följer nyckelordet extern i en extern_alias_directive.
Ett fel uppstår om ett program deklarerar ett externt alias som ingen extern definition har angetts för.
Exempel: Följande program deklarerar och använder två externa alias och
X, som var ochYen representerar roten i en distinkt namnområdeshierarki:extern alias X; extern alias Y; class Test { X::N.A a; X::N.B b1; Y::N.B b2; Y::N.C c; }Programmet deklarerar förekomsten av externa alias
XochY, men de faktiska definitionerna av aliasen är externa för programmet. De identiskt namngivnaN.Bklasserna kan nu refereras till somX.N.BochY.N.B, eller, med hjälp av namnområdets aliaskvalificerare,X::N.BochY::N.B. slutexempel
14.5 Användning av direktiv
14.5.1 Allmänt
Med hjälp av direktiv underlättas användningen av namnområden och typer som definierats i andra namnområden. Användning av direktiv påverkar namnmatchningsprocessen för namespace_or_type_names (§7.8) och simple_name(§12.8.4), men till skillnad från deklarationer bidrar using_directiveinte nya medlemmar till de underliggande deklarationsutrymmena i kompileringsenheterna eller namnrymderna inom vilka de används.
using_directive
    : using_alias_directive
    | using_namespace_directive
    | using_static_directive    
    ;
En using_alias_directive (§14.5.2) introducerar ett alias för ett namnområde eller en typ.
En using_namespace_directive (§14.5.3) importerar typmedlemmarna i ett namnområde.
En using_static_directive (§14.5.4) importerar kapslade typer och statiska medlemmar av en typ.
Omfånget för en using_directive sträcker sig över namespace_member_declarations av dess omedelbart innehållande kompileringsenhet eller namnområdestext. Omfånget för en using_directive innehåller inte dess peer-using_directives. Därför påverkar peer-using_directiveinte varandra, och den ordning i vilken de skrivs är obetydlig. Omfånget för en extern_alias_directive innehåller däremot de using_directivesom definierats i samma kompileringsenhet eller namnområdestext.
14.5.2 Använda aliasdirektiv
En using_alias_directive introducerar en identifierare som fungerar som ett alias för ett namnområde eller en typ i den omedelbart omslutande kompileringsenheten eller namnområdestexten.
using_alias_directive
    : 'using' identifier '=' namespace_or_type_name ';'
    ;
I globala attribut och medlemsdeklarationer i en kompileringsenhet eller namnområdestext som innehåller en using_alias_directive kan identifieraren som introducerades av using_alias_directive användas för att referera till det angivna namnområdet eller typen.
Example:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }Ovan, inom medlemsdeklarationer i namnområdet,
N3är ett alias förA, och därför härleds klassenN1.N2.Afrån klassenN3.B.N1.N2.ASamma effekt kan erhållas genom att skapa ett aliasRförN1.N2och sedan referera tillR.A:namespace N3 { using R = N1.N2; class B : R.A {} }slutexempel
Inom användning av direktiv, globala attribut och medlemsdeklarationer i en kompileringsenhet eller namnområdestext som innehåller en extern_alias_directive kan identifieraren som introducerades av extern_alias_directive användas för att referera till det associerade namnområdet.
Exempel: Till exempel:
namespace N1 { extern alias N2; class B : N2::A {} }Ovan, inom medlemsdeklarationer i
N1namnområdet,N2är ett alias för ett namnområde vars definition är extern mot programmets källkod. KlassenN1.Bhärleds från klassenN2.A. Samma effekt kan erhållas genom att skapa ett aliasAförN2.Aoch sedan referera tillA:namespace N1 { extern alias N2; using A = N2::A; class B : A {} }slutexempel
Ett extern_alias_directive eller using_alias_directive gör ett alias tillgängligt i en viss kompileringsenhet eller namnområdestext, men det bidrar inte några nya medlemmar till det underliggande deklarationsutrymmet. Med andra ord är ett aliasdirektiv inte transitivt, utan påverkar snarare bara kompileringsenheten eller namnområdestexten där det inträffar.
Exempel: I följande kod
namespace N3 { extern alias R1; using R2 = N1.N2; } namespace N3 { class B : R1::A, R2.I {} // Error, R1 and R2 unknown }omfången för de aliasdirektiv som inför
R1ochR2endast omfattar medlemsdeklarationer i namnområdestexten där de finns, såR1ochR2är okända i den andra namnområdesdeklarationen. Om du placerar aliasdirektiven i den innehållande kompileringsenheten blir aliaset dock tillgängligt i båda namnområdesdeklarationerna:extern alias R1; using R2 = N1.N2; namespace N3 { class B : R1::A, R2.I {} } namespace N3 { class C : R1::A, R2.I {} }slutexempel
Varje extern_alias_directive eller using_alias_directive i en compilation_unit eller namespace_body bidrar med ett namn till aliasdeklarationsutrymmet (§7.3) av den omedelbart omslutande compilation_unit eller namespace_body. Aliasdirektivets identifierare ska vara unik inom motsvarande aliasdeklarationsutrymme. Aliasidentifieraren behöver inte vara unik inom det globala deklarationsutrymmet eller deklarationsutrymmet för motsvarande namnområde.
Example:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // OkDet använda aliaset med namnet
Xorsakar ett fel eftersom det redan finns ett alias med namnetXi samma kompileringsenhet. Klassen med namnetYstår inte i konflikt med det externa aliaset med namnetYeftersom dessa namn läggs till i distinkta deklarationsutrymmen. Det förra läggs till i det globala deklarationsutrymmet och det senare läggs till i aliasdeklarationsutrymmet för den här kompileringsenheten.När ett aliasnamn matchar namnet på en medlem i ett namnområde ska användningen av något av dessa vara lämpligt kvalificerat:
namespace N1.N2 { class B {} } namespace N3 { class A {} class B : A {} } namespace N3 { using A = N1.N2; using B = N1.N2.B; class W : B {} // Error: B is ambiguous class X : A.B {} // Error: A is ambiguous class Y : A::B {} // Ok: uses N1.N2.B class Z : N3.B {} // Ok: uses N3.B }I den andra namnområdestexten för
N3resulterar okvalificerad användning avBett fel, eftersomN3innehåller en medlem med namnetBoch namnområdestexten som också deklarerar ett alias med namnetB; på samma sätt förA. KlassenN3.Bkan refereras till somN3.Bellerglobal::N3.B. AliasetAkan användas i en kvalificerad aliasmedlem (§14.8), till exempelA::B. AliasetBär i princip värdelöst. Det kan inte användas i en qualified_alias_member eftersom endast namnområdesalias kan användas i en qualified_alias_member ochBalias en typ.slutexempel
Precis som vanliga medlemmar döljs namn som introduceras av alias_directives av medlemmar med liknande namn i kapslade omfång.
Exempel: I följande kod
using R = N1.N2; namespace N3 { class R {} class B: R.A {} // Error, R has no member A }referensen till
R.Ai deklarationen avBorsakar ett kompileringsfel eftersomRrefererar tillN3.R, inteN1.N2.slutexempel
Den ordning i vilken extern_alias_directives skrivs har ingen betydelse. På samma sätt har den ordning i vilken using_alias_directives skrivs ingen betydelse, men alla using_alias_directives ska komma efter alla extern_alias_directives i samma kompileringsenhet eller namnområdestext. 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_directivei den samlingsenhet eller namnområdestext som omedelbart innehåller kompileringsenheter, men kan påverkas av extern_alias_directives i den omedelbart innehållande kompileringsenheten eller namnområdestexten. Med andra ord löses namespace_or_type_name av en using_alias_directive som om den omedelbart innehåller kompileringsenhet eller namnområdestext inte hade några using_directives men har rätt uppsättning extern_alias_directives.
Exempel: I följande kod
namespace N1.N2 {} namespace N3 { extern alias X; using R1 = X::N; // OK using R2 = N1; // OK using R3 = N1.N2; // OK using R4 = R2.N2; // Error, R2 unknown }den senaste using_alias_directive resulterar i ett kompileringsfel eftersom det inte påverkas av föregående using_alias_directive. Den första using_alias_directive resulterar inte i ett fel eftersom omfånget för det externa aliaset X innehåller using_alias_directive.
slutexempel
En using_alias_directive kan skapa ett alias för valfritt namnområde eller typ, inklusive namnområdet där det visas och alla namnområden eller typer som är kapslade i namnområdet.
Å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.
Exempel: Givet
namespace N1.N2 { class A {} } namespace N3 { using R1 = N1; using R2 = N1.N2; class B { N1.N2.A a; // refers to N1.N2.A R1.N2.A b; // refers to N1.N2.A R2.A c; // refers to N1.N2.A } }namnen
N1.N2.A, , ochR1.N2.Aär likvärdiga och alla refererar till klassdeklarationen vars fullständigt kvalificerade namn ärR2.AN1.N2.A.slutexempel
Även om varje del av en partiell typ (§15.2.7) deklareras inom samma namnområde, skrivs delarna vanligtvis inom olika namnområdesdeklarationer. Därför kan olika extern_alias_directives och using_directives finnas för varje del. Vid tolkning av enkla namn (§12.8.4) inom en del beaktas endast de extern_alias_directives och using_directivei namnområdets organ och kompileringsenhet som omger den delen. Detta kan leda till att samma identifierare har olika betydelser i olika delar.
Example:
namespace N { using List = System.Collections.ArrayList; partial class A { List x; // x has type System.Collections.ArrayList } } namespace N { using List = Widgets.LinkedList; partial class A { List y; // y has type Widgets.LinkedList } }slutexempel
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.
Example:
namespace N1 { class A<T> { class B {} } } namespace N2 { using W = N1.A; // Error, cannot name unbound generic type using X = N1.A.B; // Error, cannot name unbound generic type using Y = N1.A<int>; // Ok, can name closed constructed type using Z<T> = N1.A<T>; // Error, using alias cannot have type parameters }slutexempel
14.5.3 Använda namnområdesdirektiv
En using_namespace_directive importerar de typer som finns i ett namnområde till den omedelbart omslutande kompileringsenheten eller namnområdestexten, vilket gör att identifieraren för varje typ kan användas utan kvalificering.
using_namespace_directive
    : 'using' namespace_name ';'
    ;
I medlemsdeklarationer i en kompileringsenhet eller namnområdestext som innehåller en using_namespace_directive kan de typer som finns i det angivna namnområdet refereras direkt.
Example:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }Ovan, inom medlemsdeklarationer i
N3namnområdet, är typen medlemmar avN1.N2direkt tillgängliga, och därmed härleds klassenN3.Bfrån klassenN1.N2.A.slutexempel
En using_namespace_directive importerar typerna i det angivna namnområdet, men importerar inte kapslade namnområden.
Exempel: I följande kod
namespace N1.N2 { class A {} } namespace N3 { using N1; class B : N2.A {} // Error, N2 unknown }using_namespace_directive importerar typerna i
N1, men inte de namnområden som är kapslade iN1. Referensen tillN2.Ai deklarationen resulterarBalltså i ett kompileringsfel eftersom inga medlemmar med namnetN2finns i omfånget.slutexempel
Till skillnad från en using_alias_directive kan en using_namespace_directive importera typer vars identifierare redan har definierats i den omslutande kompileringsenheten eller namnområdestexten. I själva verket döljs namn som importeras av en using_namespace_directive av medlemmar med liknande namn i den omslutande kompileringsenheten eller namnområdestexten.
Example:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }Här refererar i medlemsdeklarationer i
N3namnområdetAtill i ställetN3.AförN1.N2.A.slutexempel
Eftersom namn kan vara tvetydiga när fler än ett importerat namnområde introducerar samma typnamn är en using_alias_directive användbar för att skilja referensen åt.
Exempel: I följande kod
namespace N1 { class A {} } namespace N2 { class A {} } namespace N3 { using N1; using N2; class B : A {} // Error, A is ambiguous }både
N1ochN2innehåller en medlemA, och eftersomN3importer av båda är hänvisningarAiN3ett kompileringsfel. I den här situationen kan konflikten lösas antingen genom kvalificering av referenser till , eller genom attAinföra en using_alias_directive som väljer en vissA. Till exempel:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }slutexempel
Om fler än ett namnområde eller en typ som importerats av using_namespace_directives eller using_static_directives i samma kompileringsenhet eller namnområdestext innehåller typer eller medlemmar med samma namn, betraktas referenser till det namnet som en simple_name tvetydiga.
Example:
namespace N1 { class A {} } class C { public static int A; } namespace N2 { using N1; using static C; class B { void M() { A a = new A(); // Ok, A is unambiguous as a type-name A.Equals(2); // Error, A is ambiguous as a simple-name } } }
N1innehåller en typmedlemA, ochCinnehåller ett statiskt fältAoch eftersomN2importerar båda, refererarAsom en simple_name är tvetydig och ett kompileringsfel.slutexempel
Precis som en using_alias_directive bidrar inte en using_namespace_directive några nya medlemmar till det underliggande deklarationsutrymmet i kompileringsenheten eller namnområdet, utan påverkar snarare bara kompileringsenheten eller namnområdestexten där den visas.
Den namespace_name som refereras av en using_namespace_directive matchas på samma sätt som namespace_or_type_name som refereras av en using_alias_directive. Därför påverkar using_namespace_directivei samma kompileringsenhet eller namnområdestext inte varandra och kan skrivas i valfri ordning.
14.5.4 Användning av statiska direktiv
En using_static_directive importerar kapslade typer och statiska medlemmar som finns direkt i en typdeklaration till den omedelbart omslutande kompileringsenheten eller namnområdestexten, vilket gör att identifieraren för varje medlem och typ kan användas utan kvalificering.
using_static_directive
    : 'using' 'static' type_name ';'
    ;
I medlemsdeklarationer i en kompileringsenhet eller namnområdestext som innehåller en using_static_directive kan tillgängliga kapslade typer och statiska medlemmar (förutom tilläggsmetoder) som finns direkt i deklarationen av den angivna typen refereras direkt.
Example:
namespace N1 { class A { public class B {} public static B M() => new B(); } } namespace N2 { using static N1.A; class C { void N() { B b = M(); } } }I föregående kod, inom medlemsdeklarationer i
N2namnområdet, är de statiska medlemmarna och kapslade typerna avN1.Adirekt tillgängliga, och metodenNkan därför referera till bådeBochMmedlemmar iN1.A.slutexempel
En using_static_directive importerar inte tilläggsmetoder direkt som statiska metoder, men gör dem tillgängliga för anrop av tilläggsmetod (§12.8.10.3).
Example:
namespace N1 { static class A { public static void M(this string s){} } } namespace N2 { using static N1.A; class B { void N() { M("A"); // Error, M unknown "B".M(); // Ok, M known as extension method N1.A.M("C"); // Ok, fully qualified } } }using_static_directive importerar tilläggsmetoden
MiN1.A, men bara som en tilläggsmetod. Därför resulterar den första referensen iMbrödtextenB.Ni ett kompileringsfel eftersom inga medlemmar med namnetMfinns i omfånget.slutexempel
En using_static_directive importerar endast medlemmar och typer som deklarerats direkt i den angivna typen, inte medlemmar och typer som deklarerats i basklasser.
Example:
namespace N1 { class A { public static void M(string s){} } class B : A { public static void M2(string s){} } } namespace N2 { using static N1.B; class C { void N() { M2("B"); // OK, calls B.M2 M("C"); // Error. M unknown } } }using_static_directive importerar metoden
M2iN1.B, men importerar inte metodenMiN1.A. Referensen tillMi brödtextenC.Ni resulterar därför i ett kompileringsfel eftersom inga medlemmar med namnetMfinns i omfånget. Utvecklare måste lägga till ett andrausing staticdirektiv för att ange att metoderna iN1.Aockså ska importeras.slutexempel
Tvetydigheter mellan flera using_namespace_directives och using_static_directives diskuteras i §14.5.3.
14.6 Medlemsdeklarationer för namnområde
En namespace_member_declaration är antingen en namespace_declaration (§14.3) eller en type_declaration (§14.7).
namespace_member_declaration
    : namespace_declaration
    | type_declaration
    ;
En kompileringsenhet eller en namnområdestext kan innehålla namespace_member_declarations, och sådana deklarationer bidrar med nya medlemmar till det underliggande deklarationsutrymmet för den innehållande kompileringsenheten eller namnområdestexten.
14.7 Typdeklarationer
En type_declaration är en class_declaration (§15.2), en struct_declaration (§16.2), en interface_declaration (§19.2), en enum_declaration (§20.2) eller en delegate_declaration (§21.2).
type_declaration
    : class_declaration
    | struct_declaration
    | interface_declaration
    | enum_declaration
    | delegate_declaration
    ;
En type_declaration kan ske som en deklaration på den översta nivån i en kompileringsenhet eller som en medlemsdeklaration inom ett namnområde, en klass eller en struct.
När en typdeklaration för en typ T inträffar som en toppnivådeklaration i en kompileringsenhet är det fullständigt kvalificerade namnet (§7.8.3) av typdeklarationen detsamma som det okvalificerade namnet på deklarationen (§7.8.2). När en typdeklaration för en typ T inträffar inom ett namnområde, en klass eller en struct-deklaration är det fullständigt kvalificerade namnet (S.N) av typdeklarationen , där S är det fullständigt kvalificerade namnet på det innehållande namnområdet, klassen eller structdeklarationen och N är det okvalificerade namnet på deklarationen.
En typ som deklareras i en klass, ett gränssnitt eller en struct kallas för en kapslad typ (§15.3.9).
De tillåtna åtkomstmodifierarna och standardåtkomsten för en typdeklaration beror på i vilket sammanhang deklarationen äger rum (§7.5.2):
- Typer som deklareras i kompileringsenheter eller namnområden kan ha publicellerinternalkomma åt. Standardvärdet ärinternalåtkomst.
- Typer som deklareras i klasser kan ha public,protected internal,protected,private protected,internalellerprivateåtkomst. Standardvärdet ärprivateåtkomst.
- Typer som deklareras i structs kan ha public,internalellerprivateåtkomst. Standardvärdet ärprivateåtkomst.
14.8 Kvalificerad aliasmedlem
14.8.1 Allmänt
Namnområdesaliaskvalificeraren :: gör det möjligt att garantera att typnamnsökningar inte påverkas av introduktionen av nya typer och medlemmar. Namnområdesaliaskvalificeraren visas alltid mellan två identifierare som kallas för vänster- och högeridentifierare. Till skillnad från den vanliga . kvalificeraren, letas den vänstra identifieraren för kvalificeringen :: endast upp som extern eller med hjälp av alias.
En qualified_alias_member ger explicit åtkomst till det globala namnområdet och till externt eller med hjälp av alias som kan vara dolda av andra entiteter.
qualified_alias_member
    : identifier '::' identifier type_argument_list?
    ;
En qualified_alias_member kan användas som en namespace_or_type_name (§7.8) eller som vänster operande i en member_access (§12.8.7).
En qualified_alias_member består av två identifierare, så kallade vänster- och högeridentifierare, avgränsade med :: token och eventuellt följt av en type_argument_list. När den vänstra identifieraren är global söks det globala namnområdet efter den högra identifieraren. För andra vänsteridentifierare söks identifieraren upp som extern eller med alias (§14.4 och §14.5.2). Ett kompileringsfel uppstår om det inte finns något sådant alias eller om aliaset refererar till en typ. Om aliaset refererar till ett namnområde söks namnområdet efter den högra identifieraren.
En qualified_alias_member har ett av två formulär:
- 
              N::I<A₁, ..., Aₑ>, därNochIrepresenterar identifierare och<A₁, ..., Aₑ>är en typargumentlista. (eär alltid minst en.)
- 
              N::I, därNochIrepresenterar identifierare. (I det här falleteanses vara noll.)
Med den här notationen bestäms innebörden av en qualified_alias_member på följande sätt:
- Om När identifierarenglobalsöksIdet globala namnområdet efter :- Om det globala namnområdet innehåller ett namnområde med namnet Iocheär noll refererar qualified_alias_member till namnområdet.
- Annars, om det globala namnområdet innehåller en icke-generisk typ med namnet Iocheär noll, refererar qualified_alias_member till den typen.
- Annars, om det globala namnområdet innehåller en typ med namnet Isom haretypparametrar, refererar qualified_alias_member till den typen som skapats med de angivna typargumenten.
- Annars är qualified_alias_member odefinierat och ett kompileringsfel inträffar.
 
- Om det globala namnområdet innehåller ett namnområde med namnet 
- 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 är qualified_alias_member odefinierad och ett kompileringsfel inträffar.
- Om namnområdesdeklarationen eller kompileringsenheten annars innehåller en extern_alias_directive eller using_alias_directive som associeras Nmed ett namnområde:- Om namnområdet som är associerat med Ninnehåller ett namnområde med namnetIocheär noll refererar qualified_alias_member till namnområdet.
- Om namnområdet som är associerat med Ninnehåller en icke-generisk typ med namnetIocheär noll refererar qualified_alias_member till den typen.
- Annars, om namnområdet som är associerat med Ninnehåller en typ med namnetIsom haretypparametrar, refererar qualified_alias_member till den typen som skapats med de angivna typargumenten.
- Annars är qualified_alias_member odefinierat och ett kompileringsfel inträffar.
 
- Om namnområdet som är associerat med 
 
- Annars är qualified_alias_member odefinierat och ett kompileringsfel inträffar.
Exempel: I koden:
using S = System.Net.Sockets; class A { public static int x; } class C { public void F(int A, object S) { // Use global::A.x instead of A.x global::A.x += A; // Use S::Socket instead of S.Socket S::Socket s = S as S::Socket; } }-klassen
Arefereras till ochglobal::AtypenSystem.Net.Sockets.Socketrefereras till medS::Socket. Att användaA.xochS.Socketi stället skulle ha orsakat kompileringsfel eftersomAochSskulle ha matchat parametrarna.slutexempel
Obs! Identifieraren
globalhar endast särskild betydelse när den används som vänsteridentifierare för en qualified_alias_name. Det är inte ett nyckelord och det är inte i sig ett alias. det är ett kontextuellt nyckelord (§6.4.4). I koden:class A { } class C { global.A x; // Error: global is not defined global::A y; // Valid: References A in the global namespace }användning
global.Aorsakar ett kompileringsfel eftersom det inte finns någon entitet med namnetglobali omfånget. Om någon entitet med namnet global fanns i omfångetglobalskulle inglobal.Aha matchats till den entiteten.Om du använder
globalsom vänsteridentifierare för en qualified_alias_member alltid orsakar en sökning iglobalnamnområdet, även om det finns ett alias med namnetglobal. I koden:using global = MyGlobalTypes; class A { } class C { global.A x; // Valid: References MyGlobalTypes.A global::A y; // Valid: References A in the global namespace }
global.AlöserMyGlobalTypes.Atill ochglobal::Amatchar klassenAi det globala namnområdet.slutkommentar
14.8.2 Aliasens unika egenskaper
Varje kompileringsenhet och namnområdestext har ett separat deklarationsutrymme för externa alias och med hjälp av alias. Även om namnet på ett externt alias eller ett alias ska vara unikt inom uppsättningen externa alias och använda alias som deklareras i den omedelbart innehållande kompileringsenheten eller namnområdestexten, tillåts ett alias ha samma namn som en typ eller ett namnområde så länge det endast används med :: kvalificeraren.
Exempel: I följande:
namespace N { public class A {} public class B {} } namespace N { using A = System.IO; class X { A.Stream s1; // Error, A is ambiguous A::Stream s2; // Ok } }namnet
Ahar två möjliga betydelser i den andra namnområdestexten eftersom både klassenAoch det använda aliasetAfinns i omfånget. Därför är användningen avAi det kvalificerade namnetA.Streamtvetydig och orsakar ett kompileringsfel. Användning avAmed kvalificeraren::är dock inte ett fel eftersomAdet endast är ett namnområdesalias.slutexempel
ECMA C# draft specification