Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
14.1 Általános
A C#-programok névterek használatával vannak rendszerezve. A névterek mind a programok "belső" szervezeti rendszereként, mind pedig "külső" szervezeti rendszerként használatosak – ez a más programok számára elérhető programelemek bemutatásának módja.
A névterek használatának megkönnyítése érdekében irányelveket (14.6. §) és globális irányelveket (14.5. §) kell alkalmazni.
14.2 Fordítási egységek
A compilation_unit nullából vagy több extern_alias_directive, majd nullából vagy több global_using_directives-ből, majd nullából vagy több using_directives-ből, majd nullából vagy egy global_attributes , majd egy compilation_unit_body áll. A compilation_unit_body lehet nulla vagy több statement_list, majd nulla vagy több namespace_member_declarations, vagy file_scoped_namespace_declaration. A compilation_unit határozza meg a bemenet általános szerkezetét.
compilation_unit
: extern_alias_directive* using_directive* global_attributes? compilation_unit_body
;
compilation_unit_body
: statement_list* namespace_member_declaration*
| file_scoped_namespace_declaration
;
A C#-programok egy vagy több fordítási egységből állnak. Egy C#-program fordításakor az összes fordítási egység együtt lesz feldolgozva. Így a fordítási egységek egymástól függhetnek, esetleg körkörös módon.
A fordítási egység extern_alias_directives-i hatással vannak a fordítási egység global_using_directive, using_directives, global_attributes és compilation_unit_body , de nincs hatással más fordítási egységekre.
A fordítási egység using_directiveglobal_attributes éscompilation_unit_body befolyásolják, de nincs hatással más fordítási egységekre.
A fordítási egység global_using_directivea program összes fordítási egységének global_attributes és namespace_member_declarations-jét érinti.
A fordítási egység global_attributes (23.3. §) lehetővé teszi a célszerelvény és modul attribútumainak specifikációját. A szerelvények és modulok fizikai tárolóként működnek a típusok esetében. Egy szerelvény több fizikailag különálló modulból állhat.
A program egyes fordítási egységeinek namespace_member_declarationvagy file_scoped_namespace_declaration a tagok egy globális névtér nevű egyetlen deklarációs térhez járulnak hozzá.
A file_scoped_namespace_declaration a szemantikailag egyenértékű namespace_declaration megfelelő tagok közreműködésével (14.3. §).
Example:
// File A.cs: class A {} // File B.cs: class B {}A két fordítási egység hozzájárul az egyetlen globális névtérhez, ebben az esetben két osztályt deklarál a teljes névvel
AésB. Mivel a két összeállítási egység ugyanahhoz a deklarációs területhez járul hozzá, hiba lett volna, ha mindegyik egy azonos nevű tag deklarációját tartalmazza.záró példa
14.3 Névtér deklarációk
A namespace_declaration a kulcsszó névteréből, majd egy névtérnévből és egy törzsből állnak, amelyet igény szerint pontosvessző követ. A file_scoped_namespace_declaration a kulcsszóból namespace, majd egy névtérnévből, pontosvesszőből és extern_alias_directives, using_directives és type_declarationválasztható listájából állnak.
namespace_declaration
: 'namespace' qualified_identifier namespace_body ';'?
;
file_scoped_namespace_declaration
: 'namespace' qualified_identifier ';' extern_alias_directive* using_directive*
type_declaration*
;
qualified_identifier
: identifier ('.' identifier)*
;
namespace_body
: '{' extern_alias_directive* using_directive*
namespace_member_declaration* '}'
;
A namespace_declaration egy compilation_unit legfelső szintű deklarációjaként vagy egy másik namespace_declaration belüli tagi deklarációként is előfordulhat. Ha egy namespace_declaration egy compilation_unit legfelső szintű deklarációjaként történik, a névtér a globális névtér tagjává válik. Ha egy namespace_declaration egy másik namespace_declaration belül történik, a belső névtér a külső névtér tagjává válik. A névtér nevének mindkét esetben egyedinek kell lennie az azt tartalmazó névtéren belül.
A file_scoped_namespace_declaration csak legfelső szintű deklarációként fordulhat elő egy compilation_unit. Így a deklarált névtér a globális névtér tagjává válik.
A névterek implicitek public , és a névtér deklarációja nem tartalmazhat hozzáférési módosítókat.
Egy namespace_body belül az opcionális using_directivemás névterek, típusok és tagok nevét importálják, így közvetlenül hivatkozhatnak rájuk a minősített nevek helyett. A választható namespace_member_declarationtagokat a névtér deklarációs területéhez. Vegye figyelembe, hogy minden using_directivemeg kell jelennie a tagi nyilatkozatok előtt.
Egy file_scoped_namespace_declaration az opcionális using_directiveimportálják az egyéb névterek, típusok és tagok nevét, így közvetlenül hivatkozhatnak rájuk a minősített nevek helyett. Az opcionális type_declarationtagokat a névtér deklarációs területéhez. Vegye figyelembe, hogy minden using_directivemeg kell jelennie a típusdeklarációk előtt.
Egy namespace_declaration és file_scoped_namespace_declaration qualified_identifier lehet egyetlen azonosító vagy azonosítósorozat, amelyet "." jogkivonatok választanak el. Az utóbbi űrlap lehetővé teszi, hogy a program több névtérdeklaráció lexikális beágyazása nélkül definiáljon beágyazott névteret.
Example:
namespace N1.N2 { class A {} class B {} }szemantikailag egyenértékű a
namespace N1 { namespace N2 { class A {} class B {} } }záró példa
A file_scoped_namespace_declaration lehetővé teszi, hogy a névtér-deklarációt kísérő { … } blokk nélkül lehessen megírni.
Example:
namespace Name; using System; class C { }szemantikailag egyenértékű a
namespace Name { using System; class C { } }záró példa
A file_scoped_namespace_declaration ugyanazzal a namespace_declaration kezeli a compilation_unit ugyanazon a helyen, ugyanazzal a qualified_identifier. A file_scoped_namespace_declaration extern_alias_directives, using_directives és type_declarations-e úgy viselkednek, mintha ugyanabban a sorrendben deklarálták volna őket az namespace_declaration namespace_body belül.
Megjegyzés: A nyelvtani meghatározásnak megfelelően a fordítási egység nem tartalmazhat file_scoped_namespace_declaration és namespace_declaration. Nem tartalmazhat több file_scoped_namespace_declarations-t. Nem tartalmazhat file_scoped_namespace_declaration és legfelső szintű utasításokatis. type_declarations nem előzhet meg file_scoped_namespace_declaration. végjegyzet
A különböző fordítási egységek a namespace_member_declaration vagy file_scoped_namespace_declaration szintaxissal is hozzájárulhatnak ugyanahhoz a névtérhez.
A névterek nyitott végűek, és két azonos teljes névvel rendelkező névtér-deklaráció (7.8.3. §) járul hozzá ugyanahhoz a deklarációs térhez (7.3. §).
Példa: Az alábbi kódban
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }a fenti két névtér-deklaráció ugyanahhoz a deklarációs térhez járul hozzá, ebben az esetben két osztályt deklarál a teljes névvel
N1.N2.AésN1.N2.B. Mivel a két deklaráció ugyanahhoz a deklarációs térhez járul hozzá, hiba lett volna, ha mindegyik egy azonos nevű tag deklarációját tartalmazza.záró példa
A file_scoped_namespace_declaration lehetővé teszi, hogy a névtér-deklarációt kísérő { … } blokk nélkül lehessen megírni.
Example:
namespace Name; using System; class C { }szemantikailag egyenértékű a
namespace Name { using System; class C { } }záró példa
A file_scoped_namespace_declaration ugyanazzal a namespace_declaration kezeli a compilation_unit ugyanazon a helyen, ugyanazzal a qualified_identifier. A file_scoped_namespace_declaration extern_alias_directives, using_directives és type_declarations-e úgy viselkednek, mintha ugyanabban a sorrendben deklarálták volna őket az namespace_declaration namespace_body belül.
Megjegyzés: A nyelvtani meghatározásnak megfelelően a fordítási egység nem tartalmazhat file_scoped_namespace_declaration és namespace_declaration. Nem tartalmazhat több file_scoped_namespace_declarations-t. Nem tartalmazhat file_scoped_namespace_declaration és legfelső szintű utasításokatis. type_declarations nem előzhet meg file_scoped_namespace_declaration. végjegyzet
A különböző fordítási egységek a namespace_member_declaration vagy file_scoped_namespace_declaration szintaxissal is hozzájárulhatnak ugyanahhoz a névtérhez.
14.4 Extern alias irányelvek
Egy extern_alias_directive egy névtér aliasaként szolgáló azonosítót vezet be. Az aliasos névtér specifikációja kívül esik a program forráskódán, és az aliasos névtér beágyazott névtereire is vonatkozik.
extern_alias_directive
: 'extern' 'alias' identifier ';'
;
A extern_alias_directive hatókörét a 7.7.1.
Egy extern_alias_directive tartalmazó összeállítási egységben vagy névtértörzsben a extern_alias_directive által bevezetett azonosító használható az aliasos névtérre való hivatkozáshoz. Fordítási időhiba, hogy az azonosító legyen a szó global.
A extern_alias_directive által bevezetett alias nagyon hasonlít a using_alias_directive által bevezetett aliashoz. Az extern_alias_directives és using_alias_directiverészletesebb ismertetését a 14.6.2.
aliasegy környezetfüggő kulcsszó (6.4.4.4. §), és csak akkor van különleges jelentése, ha azonnal követi a extern egy extern_alias_directive.
Hiba akkor fordul elő, ha egy program olyan extern aliast deklarál, amelyhez nincs megadva külső definíció.
Példa: A következő program két extern aliast deklarál és használ,
XamelyekYmindegyike egy különálló névtérhierarchia gyökerét jelöli:extern alias X; extern alias Y; class Test { X::N.A a; X::N.B b1; Y::N.B b2; Y::N.C c; }A program deklarálja a kiirtott aliasok
Xmeglétét, deYaz aliasok tényleges definíciói külsőek a programon. A névtér alias-minősítője ésN.Ba névtér aliasának minősítőjekéntX.N.BY.N.Bés néven hivatkozhatX::N.Baz azonos nevűY::N.Bosztályokra. záró példa
14.5 Globális irányelvek
14.5.1 Általános
A globális használatról szóló irányelv a fordítási egység legfelső szintjén lévő, használatban lévő irányelv (14.6. §).
global_using_directive
: global_using_alias_directive
| global_using_namespace_directive
| global_using_static_directive
;
Megjegyzés: A global_using_directive hatóköre a program összes fordítási egységének namespace_member_declarations-jára terjed ki. A global_using_directive hatóköre nem tartalmaz más global_using_directive. Így a társ global_using_directivevagy egy másik fordítási egységből származók nem befolyásolják egymást, és az írásuk sorrendje jelentéktelen. A global_using_directive hatóköre nem foglalja magában a program bármely összeállítási egységében azonnal található using_directive.
A global_using_directive programhoz való hozzáadásának hatása egy hasonló using_directive hozzáadásának hatása, amely ugyanahhoz a célnévtérhez feloldható, vagy a program összes fordítási egységéhez beírható. A global_using_directive célja azonban az azt tartalmazó fordítási egység kontextusában lesz feloldva. végjegyzet
14.5.2 Globális alias irányelvek használatával
A global_using_alias_directive olyan azonosítót vezet be, amely aliasként szolgál egy névtérhez vagy típushoz a programban.
global_using_alias_directive
: 'global' using_alias_directive
;
A global_using_alias_directive tartalmazó programok bármely összeállítási egységében található tagdeklarációkban a global_using_alias_directive által bevezetett azonosító használható a megadott névtérre vagy típusra való hivatkozáshoz.
A global_using_alias_directiveazonosítójának egyedinek kell lennie a global_using_alias_directive tartalmazó program bármely fordítási egységének deklarációs területén belül.
A normál tagokhoz hasonlóan a global_using_alias_directiveáltal bevezetett neveket is elrejtik a beágyazott hatókörök hasonló nevű tagjai.
A global_using_alias_directiveírási sorrendjének nincs jelentősége, és a global_using_alias_directive hivatkozott namespace_or_type_name felbontását nem befolyásolja maga a global_using_alias_directive, sem a program más global_using_directivevagy using_directives. Más szóval, a global_using_alias_directive namespace_or_type_name úgy oldják fel, mintha az azonnal tartalmazó összeállítási egységnek nem volt using_directives-e, és az egész programnak nem volt global_using_directives. A global_using_alias_directive azonban hatással lehet extern_alias_directiveaz azonnal tartalmazó összeállítási egységben.
A global_using_alias_directive bármilyen névtérhez vagy típushoz létrehozhat aliast.
A névtér vagy a típus aliason keresztüli elérése pontosan ugyanazt az eredményt eredményezi, mint az adott névtér elérése vagy a deklarált név alapján történő beírás.
Az aliasok használatával zárt, konstruktált típust nevezhet el, de nem nevezhet el kötetlen általános típusdeklarációt típusargumentumok megadása nélkül.
14.5.3 Globális névtér-irányelvek használatával
Egy global_using_namespace_directive a névtérben található típusokat importálja a programba, így az egyes típusok azonosítója minősítés nélkül használható.
global_using_namespace_directive
: 'global' using_namespace_directive
;
Egy global_using_namespace_directive tartalmazó program tagdeklarációiban a megadott névtérben található típusok közvetlenül hivatkozhatók.
A global_using_namespace_directive importálja a megadott névtérben található típusokat, de nem importál beágyazott névtereket.
A global_using_alias_directive ellentétben a global_using_namespace_directive importálhatnak olyan típusokat, amelyek azonosítói már definiálva vannak a program fordítási egységében. Valójában egy adott fordítási egységben a program bármely global_using_namespace_directive által importált neveket a fordítási egység hasonló nevű tagjai elrejtik.
Ha ugyanazon program global_using_namespace_directives vagy global_using_static_directiveáltal importált több névtér vagy típus azonos néven tartalmaz típusokat, akkor az adott névre type_name való hivatkozások nem egyértelműnek minősülnek.
Továbbá, ha ugyanazon program global_using_namespace_directives vagy global_using_static_directiveáltal importált több névtér vagy típus azonos néven tartalmaz típusokat vagy tagokat, az adott névre való hivatkozás simple_name nem egyértelmű.
A global_using_namespace_directive által hivatkozott namespace_name ugyanúgy oldjuk fel, mint a global_using_alias_directive hivatkozott namespace_or_type_name. Így global_using_namespace_directiveugyanabban a programban nem érintik egymást, és bármilyen sorrendben írhatók.
14.5.4 Globális statikus irányelvek használatával
A global_using_static_directive közvetlenül a típusdeklarációban található beágyazott típusokat és statikus tagokat importálja a kódoló programba, így az egyes tagok és típusok azonosítóját minősítés nélkül lehet használni.
global_using_static_directive
: 'global' using_static_directive
;
A global_using_static_directive tartalmazó program tagdeklarációiban közvetlenül az adott típus deklarációjában található akadálymentes beágyazott típusok és statikus tagok (a bővítménymetelyek kivételével) közvetlenül hivatkozhatók.
A global_using_static_directive nem importálja közvetlenül statikus metódusként a bővítménymetódusokat, hanem elérhetővé teszi őket a bővítménymetódus meghívásához.
A global_using_static_directive csak az adott típusban közvetlenül deklarált tagokat és típusokat importálja, az alaposztályokban deklarált tagokat és típusokat nem.
A több global_using_namespace_directiveés global_using_static_directives közötti kétértelműségeket a 14.5.3.
14.6 Irányelvek használata
14.6.1 Általános
A használati irányelv megkönnyíti a más névterekben definiált névterek és típusok használatát. Az irányelvek használata hatással van namespace_or_type_name s (7.8. §) és simple_name(12.8.4. §) névfeloldási folyamatára, de a deklarációkkal ellentétben a using_directive-eknem járulnak hozzá új tagokhoz azon összeállítási egységek vagy névterek mögöttes deklarációs tereihez, amelyeken belül használják őket.
using_directive
: using_alias_directive
| using_namespace_directive
| using_static_directive
;
A using_alias_directive (14.6.2. §) egy névtérhez vagy típushoz tartozó aliast vezet be.
Egy using_namespace_directive (14.6.3. §) importálja a névtér típustagokat.
Egy using_static_directive (14.6.4. §) importálja egy típus beágyazott típusait és statikus tagjait.
A using_directive hatókörét a 7.7.1.
14.6.2 Alias irányelvek használata
A using_alias_directive olyan azonosítót vezet be, amely aliasként szolgál egy névtérhez vagy típushoz az azonnali összeállítási egység vagy névtér törzsén belül.
using_alias_directive
: 'using' identifier '=' namespace_or_type_name ';'
;
A using_alias_directive tartalmazó összeállítási egység vagy névtértörzs globális attribútumaiban és tagdeklarációiban a using_alias_directive által bevezetett azonosító használható a megadott névtérre vagy típusra való hivatkozáshoz.
Example:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }A névtérben lévő tagdeklarációkon belül a névtér egy aliasa,
N3így azAosztályN1.N2.Aaz osztálybólN3.BszármazikN1.N2.A. Ugyanezt a hatást úgy érheti el, hogy létrehoz egy aliastRa következőhözN1.N2, majd hivatkozikR.Ará:namespace N3 { using R = N1.N2; class B : R.A {} }záró példa
A extern_alias_directive tartalmazó összeállítási egységben vagy névtértörzsben lévő irányelvek, globális attribútumok és tagdeklarációk használatával a extern_alias_directive által bevezetett azonosító használható a társított névtérre való hivatkozáshoz.
Példa: Például:
namespace N1 { extern alias N2; class B : N2::A {} }A névtér tagdeklarációiban
N1a fenti névtér egy olyan névtér aliasa,N2amelynek definíciója külső a program forráskódjában. Az osztályN1.Baz osztálybólN2.Aszármazik. Ugyanezt a hatást úgy érheti el, hogy létrehoz egy aliastAa következőhözN2.A, majd hivatkozikArá:namespace N1 { extern alias N2; using A = N2::A; class B : A {} }záró példa
Egy extern_alias_directive vagy using_alias_directive elérhetővé tesz egy aliast egy adott összeállítási egységben vagy névtértörzsben, de nem járul hozzá új tagokhoz az alapul szolgáló deklarációs térhez. Más szóval az alias-irányelv nem tranzitív, hanem csak a fordítási egységre vagy névtértörzsre van hatással, amelyben ez történik.
Példa: Az alábbi kódban
namespace N3 { extern alias R1; using R2 = N1.N2; } namespace N3 { class B : R1::A, R2.I {} // Error, R1 and R2 unknown }az alias-irányelvek hatókörei, amelyek csak abban a névtértörzsben lévő tagdeklarációkra terjednek ki
R1R2, amelyben azok szerepelnek, ígyR1R2nem szerepelnek a második névtér-deklarációban. Ha azonban az alias-irányelveket a fordítási egységben helyezi el, az alias mindkét névtér-deklarációban elérhetővé válik:extern alias R1; using R2 = N1.N2; namespace N3 { class B : R1::A, R2.I {} } namespace N3 { class C : R1::A, R2.I {} }záró példa
Egy compilation_unit vagy namespace_body minden extern_alias_directive vagy using_alias_directive a közvetlenül az compilation_unit vagy namespace_body tartalmazó alias deklarációs térbe (7.3. §) ad nevet. Az alias-irányelv azonosítójának egyedinek kell lennie a megfelelő alias-deklarációs területen belül. Az aliasazonosítónak nem kell egyedinek lennie a globális deklarációs térben vagy a megfelelő névtér deklarációs területén belül.
Example:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // OkA névvel ellátott
Xalias használata hibát okoz, mivel már van egy alias neveXugyanabban a fordítási egységben. A névvel ellátottYosztály nem ütközik a névvel elnevezettYextern aliassal, mivel ezek a nevek különböző deklarációs szóközökhöz vannak hozzáadva. Az előbbi hozzáadódik a globális deklarációs térhez, az utóbbi pedig a fordítási egység alias deklarációs területéhez.Ha egy aliasnév megegyezik egy névtér egy tagjának nevével, a névtér használatát megfelelően kell minősíteni:
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 }A második névtértörzsben
N3az eredmények nem minősített használataBhibát eredményez, mivelN3tartalmaz egy tagot,Bés a névtér törzsét, amely szintén névvelBrendelkező aliast deklarál; hasonlóképpen a következőhözA: . Az osztályN3.Bhivatkozásként vagyN3.Bnéven is hivatkozhatglobal::N3.B. Az aliasAegy minősített alias-tagban (14.9. §) használható, példáulA::B. Az aliasBlényegében haszontalan. Nem használható qualified_alias_member , mivel csak névtér-aliasok használhatók qualified_alias_member ésBaliasok egy típusban.záró példa
A normál tagokhoz hasonlóan a alias_directives által bevezetett neveket is elrejtik a hasonló nevű tagok a beágyazott hatókörökben.
Példa: Az alábbi kódban
using R = N1.N2; namespace N3 { class R {} class B: R.A {} // Error, R has no member A }a deklarációban szereplő
R.Ahivatkozás fordítási időt eredményez, mertBnemRN3.R.N1.N2záró példa
Az extern_alias_directiveírási sorrendjének nincs jelentősége. Hasonlóképpen, az using_alias_directiveírási sorrendjének nincs jelentősége, de minden using_alias_directives ugyanazon összeállítási egységben vagy névtértörzsben lévő összes extern_alias_directiveután kell érkeznie. A using_alias_directive által hivatkozott namespace_or_type_name felbontását nem befolyásolja az using_alias_directivevagy afordítási egységet vagy névtér törzsét közvetlenül tartalmazó using_directive, de az közvetlenül tartalmazó összeállítási egység vagy névtér törzsében lévő extern_alias_directives-ek is érinthetik. És ha a using_alias_directive azonnal tartalmazza egy fordítási egység, nem befolyásolja a global_using_directives a program. Más szóval, a using_alias_directive namespace_or_type_name úgy oldják fel, mintha az azonnal tartalmazó összeállítási egység vagy névtértörzs nem tartalmazott volna using_directives-t, és ha a using_alias_directive azonnal tartalmazza egy összeállítási egységben, a programnak nem volt global_using_directives, de a megfelelő extern_alias_directives készlettel rendelkezik.
Példa: Az alábbi kódban
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 }az utolsó using_alias_directive fordítási időt érintő hibát eredményez, mert az előző using_alias_directive nem érinti. Az első using_alias_directive nem eredményez hibát, mivel az X extern alias hatóköre tartalmazza a using_alias_directive.
záró példa
A using_alias_directive bármilyen névtérhez vagy típushoz létrehozhat aliast, beleértve a névteret, amelyen belül megjelenik, valamint bármely névteret vagy típust, amely az adott névtérbe van ágyazva.
A névtér vagy a típus aliason keresztüli elérése pontosan ugyanazt az eredményt eredményezi, mint az adott névtér elérése vagy a deklarált név alapján történő beírás.
Példa: Adott
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 } }a nevek
N1.N2.A,R1.N2.AésR2.Aegyenértékűek, és mind arra az osztálydeklarációra hivatkoznak , amelynek teljes neveN1.N2.A.záró példa
Bár a részleges típus minden része (15.2.7. §) ugyanabban a névtérben van deklarálva, a részek általában különböző névtér-deklarációkban vannak megírva. Így minden résznél különböző extern_alias_directiveés using_directivelehet jelen. Az egyszerű nevek (12.8.4.§) egy részen belüli értelmezésekor csak a névtértestek és az azt tartalmazó összeállítási egység extern_alias_directiveés using_directives-jét kell figyelembe venni. Ez azt eredményezheti, hogy ugyanaz az azonosító eltérő jelentéssel rendelkezik a különböző részekben.
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 } }záró példa
Az aliasok használatával zárt, konstruktált típust nevezhet el, de nem nevezhet el kötetlen általános típusdeklarációt típusargumentumok megadása nélkül.
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 }záró példa
14.6.3 Névtér-irányelvek használata
Egy using_namespace_directive importálja a névtérben található típusokat az azonnal belefoglalt összeállítási egységbe vagy névtértörzsbe, így az egyes típusok azonosítója minősítés nélkül használható.
using_namespace_directive
: 'using' namespace_name ';'
;
A using_namespace_directive tartalmazó összeállítási egységben vagy névtértörzsben lévő tagdeklarációkban a megadott névtérben található típusok közvetlenül hivatkozhatók.
Example:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }A névtér tagdeklarációiban a névtérben
N3lévő tag típusú tagokN1.N2közvetlenül elérhetők, így az osztályN3.Baz osztálybólN1.N2.Aszármazik.záró példa
Egy using_namespace_directive importálja a megadott névtérben található típusokat, de nem importál beágyazott névtereket.
Példa: Az alábbi kódban
namespace N1.N2 { class A {} } namespace N3 { using N1; class B : N2.A {} // Error, N2 unknown }a using_namespace_directive importálja a benne található
N1típusokat, de a beágyazottN1névterek nem. Így az eredmények deklarációjábanN2.Aszereplő hivatkozásBfordítási idejű hibába ütközik, mivel egyetlen tag sem szerepelN2a hatókörben.záró példa
A using_alias_directive ellentétben a using_namespace_directive olyan típusokat importálhatnak, amelyek azonosítói már definiálva vannak az összeállítási egység vagy a névtér törzsében. A using_namespace_directive által importált neveket valójában a hasonló nevű tagok rejtik el az összeállítási egység vagy névtér törzsében.
Example:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }Itt a névtérben lévő tagdeklarációkon belül nem
N3a névtérre, hanemAa névtérreN3.AhivatkozikN1.N2.A.záró példa
Mivel a nevek nem egyértelműk, ha egynél több importált névtér ugyanazt a típusnevet használja, a using_alias_directive hasznos lehet a hivatkozás egyértelműsítése.
Példa: Az alábbi kódban
namespace N1 { class A {} } namespace N2 { class A {} } namespace N3 { using N1; using N2; class B : A {} // Error, A is ambiguous }és
N1tartalmaz egy tagotN2, és mivelAmindkét importálást importálja, a hivatkozásN3Afordítási időt érintőN3hiba. Ebben az esetben az ütközés a hivatkozásAminősítésével vagy egy adottAbevezetésével oldható meg . Például:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }záró példa
Továbbá, ha az using_namespace_directives vagy using_static_directiveáltal importált több névtér vagy típus ugyanabban a fordítási egységben vagy névtértörzsben azonos névvel tartalmaz típusokat vagy tagokat, akkor az adott névre simple_name való hivatkozások nem egyértelműnek minősülnek.
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 } } }
N1tartalmaz egy típustagotA, ésCegy statikus mezőtAtartalmaz, és mivelN2mindkettőt importálja,Aa simple_name hivatkozás nem egyértelmű, és fordítási időhiba.záró példa
A using_alias_directive-hez hasonlóan a using_namespace_directive sem járul hozzá új tagokhoz a fordítási egység vagy névtér mögöttes deklarációs teréhez, hanem csak a fordítási egységre vagy névtértörzsre van hatással, amelyben megjelenik.
A using_namespace_directive által hivatkozott namespace_name a using_alias_directive által hivatkozott namespace_or_type_name hasonlóan oldja fel. Így using_namespace_directives ugyanabban a fordítási egységben vagy névtér törzsben nincs hatással egymásra, és bármilyen sorrendben írható.
14.6.4 Statikus irányelvek használata
A using_static_directive közvetlenül a típusdeklarációban szereplő beágyazott típusokat és statikus tagokat importálja az azonnali összeállítási egységbe vagy névtértörzsbe, lehetővé téve az egyes tagok és típusok azonosítójának minősítés nélküli használatát.
using_static_directive
: 'using' 'static' type_name ';'
;
A using_static_directive tartalmazó összeállítási egységben vagy névtértörzsben található tagdeklarációkban közvetlenül hivatkozhat az adott típus deklarációjában közvetlenül a beágyazott típusok és statikus tagok (a bővítménymetelyek kivételével).
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(); } } }Az előző kódban a névtérben lévő tagdeklarációkban
N2a statikus tagok és a beágyazott típusokN1.Aközvetlenül elérhetők, így a metódusNhivatkozni tud mind a tagokra, mind aBMtagokraN1.A.záró példa
A using_static_directive nem importálja közvetlenül statikus metódusként a bővítménymetódusokat, hanem elérhetővé teszi őket a bővítménymetódus-meghíváshoz (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 } } }a using_static_directive importálja a bővítménymetódust
MN1.A, de csak bővítménymetódusként. Így az első hivatkozásMaz eredmények törzsébenB.Nfordítási idő hibába ütközik, mivel egyetlen tag sem szerepelMa hatókörben.záró példa
A using_static_directive csak az adott típusban közvetlenül deklarált tagokat és típusokat importálja, az alaposztályokban deklarált tagokat és típusokat nem.
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 } } }a using_static_directive importálja a benne foglalt
M2metódustN1.B, de nem importálja a benne foglalt metódustMN1.A. Így az eredmények törzsébenMlévő hivatkozásC.Nfordítási idő típusú hibába ütközik, mivel egyetlen tag sem szerepelMa hatókörben. A fejlesztőknek hozzá kell adni egy másodikusing staticirányelvet, amely meghatározza, hogy a metódusokatN1.Ais importálni kell.záró példa
A több using_namespace_directives és using_static_directives közötti kétértelműségeket a 14.6.3.
14.7 Névtértag-deklarációk
A namespace_member_declarationnamespace_declaration (14.3. §) vagy type_declaration (14.8. §).
namespace_member_declaration
: namespace_declaration
| type_declaration
;
A fordítási egység vagy a névtértörzs tartalmazhat namespace_member_declarations-t, és ezek a deklarációk új tagokat adnak hozzá az azt tartalmazó összeállítási egység vagy névtértörzs mögöttes deklarációs területéhez.
14.8 Típusdeklarációk
A type_declarationclass_declaration (15.2.§), struct_declaration (16.2.§), interface_declaration (19.2.§), enum_declaration (20.2. §) vagy delegate_declaration (21.2. §).
type_declaration
: class_declaration
| struct_declaration
| interface_declaration
| enum_declaration
| delegate_declaration
;
A type_declaration egy összeállítási egység legfelső szintű deklarációjaként vagy tagdeklarációként is előfordulhat egy névtérben, osztályban vagy szerkezetben.
Ha egy típus T típusdeklarációja legfelső szintű deklarációként történik egy fordítási egységben, a típusdeklaráció teljes neve (7.8.3. §) megegyezik a deklaráció nem minősített nevével (7.8.2. §). Ha egy típus T típusdeklarációja névtérben, osztályban vagy strukturált deklarációban történik, a típusdeklaráció teljes neve (S.N), ahol S a névtér, osztály vagy szerkezet deklaráció teljes neve, és N a deklaráció nem minősített neve.
Az osztályon, interfészen vagy szerkezeten belül deklarált típusokat beágyazott típusnak nevezzük (15.3.9. §).
A megengedett hozzáférési módosítók és a típusdeklaráció alapértelmezett hozzáférése attól függ, hogy milyen környezetben történik a deklaráció (7.5.2. §):
- A fordítási egységekben vagy névterekben deklarált típusok rendelkezhetnek
publicvagyinternalérhetők el. Az alapértelmezett ainternalhozzáférés. - Az osztályokban deklarált típusok rendelkezhetnek
public,protected internal,protected,private protected,internalvagyprivatehozzáféréssel. Az alapértelmezett aprivatehozzáférés. - A szerkezetekben deklarált típusok rendelkezhetnek
publichozzáférésselinternalvagyprivatehozzáféréssel. Az alapértelmezett aprivatehozzáférés.
14.9 Minősített aliastag
14.9.1 Általános
A lehetővé teszi annak biztosítását, hogy a típusnév-kereséseket ne befolyásolja az új típusok és tagok bevezetése. A névtér alias-minősítője mindig két, bal és jobb oldali azonosítónak nevezett azonosító között jelenik meg. A normál . minősítőtől eltérően a minősítő bal oldali azonosítója :: csak externként vagy alias használatával kereshető meg.
A qualified_alias_member explicit hozzáférést biztosít a globális névtérhez, valamint a más entitások által esetleg rejtett aliasok kiirtásához vagy használatához.
qualified_alias_member
: identifier '::' identifier type_argument_list?
;
A qualified_alias_memberhasználható namespace_or_type_name (7.8.§) vagy bal operandusként egy member_access (12.8.7. §).
A qualified_alias_member két azonosítóból állnak, amelyeket bal és jobb oldali azonosítónak nevezünk, amelyeket a :: jogkivonat jelöl, és opcionálisan egy type_argument_list követ. Ha a bal oldali azonosító globális, akkor a globális névtér a jobb oldali azonosítót keresi. Bármely más bal oldali azonosító esetén az azonosítót externként vagy aliasként kell keresni (14.4. § , 14.6.2. §). Fordítási időhiba akkor fordul elő, ha nincs ilyen alias, vagy az alias egy típusra hivatkozik. Ha az alias egy névtérre hivatkozik, akkor a névtér a jobb oldali azonosítót keresi.
A qualified_alias_member két űrlap egyikével rendelkezik:
-
N::I<A₁, ..., Aₑ>, aholNésIképviseli az azonosítókat, és<A₁, ..., Aₑ>egy típusargumentumlista. (emindig legalább egy.) -
N::I, az azonosítók helyétNésIjelölését. (Ebben az esetbenenullának számít.)
Ezzel a jelöléssel egy qualified_alias_member jelentését a következőképpen határozzuk meg:
- Ha
Naz azonosítóglobal, akkor a globális névtér a következőreIkeres:- Ha a globális névtér egy névteret
Itartalmaz, ésenulla, akkor a qualified_alias_member erre a névtérre hivatkozik. - Ellenkező esetben, ha a globális névtér nem általános típusú nevet
Itartalmaz, ésenulla, akkor a qualified_alias_member erre a típusra hivatkozik. - Ellenkező esetben, ha a globális névtér tartalmaz egy típusparaméterekkel rendelkező
Itípuste, akkor a qualified_alias_member az adott típusargumentumokkal létrehozott típusra hivatkozik. - Ellenkező esetben a qualified_alias_member nincs definiálva, és fordítási időhiba lép fel.
- Ha a globális névtér egy névteret
- Ellenkező esetben a qualified_alias_member (ha van ilyen) közvetlenül tartalmazó névtér-deklarációval (14.3. §) kezdve az egyes magában foglaló névtérdeklarációval (ha van ilyen), és a qualified_alias_member tartalmazó fordítási egységgel végződik, a következő lépések lesznek kiértékelve, amíg egy entitás nem található:
- Ha a névtér-deklaráció vagy fordítási egység tartalmaz egy using_alias_directive , amely az N-t társítja egy típushoz, vagy ha egy fordítási egység elérésekor a program egy típushoz társított
Nglobal_using_alias_directive tartalmaz, akkor a qualified_alias_member nincs definiálva, és fordítási időhiba lép fel. - Ellenkező esetben, ha a névtér-deklaráció vagy fordítási egység egy névtérhez társított
Nextern_alias_directive vagy using_alias_directive tartalmaz, vagy ha egy fordítási egység elérésekor a program egy névtérhez társítottNglobal_using_alias_directive tartalmaz, akkor:- Ha a
Ntársított névtér egyInevű névteret tartalmaz, ésenulla, akkor a qualified_alias_member erre a névtérre hivatkozik. - Ellenkező esetben, ha a
Ntársított névtér egy nem általános típusú,Inevű típust tartalmaz, ésenulla, akkor a qualified_alias_member erre a típusra hivatkozik. - Ellenkező esetben, ha a
Ntársított névtér tartalmaz egyInevű típust, amelyetípusparaméterekkel rendelkezik, akkor a qualified_alias_member az adott típusargumentumokkal létrehozott típusra hivatkozik. - Ellenkező esetben a qualified_alias_member nincs definiálva, és fordítási időhiba lép fel.
- Ha a
- Ha a névtér-deklaráció vagy fordítási egység tartalmaz egy using_alias_directive , amely az N-t társítja egy típushoz, vagy ha egy fordítási egység elérésekor a program egy típushoz társított
- Ellenkező esetben a qualified_alias_member nincs definiálva, és fordítási időhiba lép fel.
Példa: A kódban:
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; } }az osztályra
Ahivatkozikglobal::A, a típusSystem.Net.Sockets.Socketpedig a következőreS::Sockethivatkozik: . A használatA.xésS.Socketahelyett fordítási időt eredményezett volna, mertASaz a paraméterekre lett volna megoldva.záró példa
Megjegyzés: Az azonosítónak
globalcsak akkor van különleges jelentése, ha egy qualified_alias_name bal oldali azonosítójaként használják. Ez nem egy kulcsszó, és maga nem alias; környezetfüggő kulcsszó (6.4.4. §). A kódban:class A { } class C { global.A x; // Error: global is not defined global::A y; // Valid: References A in the global namespace }fordítási
global.Aidő hibát okoz, mivel a hatókörben nincs elnevezettglobalentitás. Ha egy globális nevű entitás hatókörben lenne, akkorglobalazglobal.Aadott entitásra lett volna feloldva.Ha egy qualified_alias_member bal oldali azonosítójaként használ
global, az mindig keres aglobalnévtérben, még akkor is, ha van egy alias neve.globalA kódban: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.AMyGlobalTypes.Aa globális névtérben lévő osztályraglobal::Aoldja fel ésAoldja fel a feloldásokat.végjegyzet
14.9.2 Az aliasok egyedisége
Minden fordítási egység és névtér törzse külön deklarációs térrel rendelkezik a felesleges aliasok és aliasok használatához. Így míg az extern alias vagy az alias használata egyedinek kell lennie az extern aliasok halmazán belül, és a fordítási egységet vagy névtér törzsét tartalmazó közvetlenül deklarált aliasokat használja, az aliasok csak a típussal vagy névtérrel azonos nevet kaphatnak, feltéve, hogy csak a :: minősítővel használják.
Példa: Az alábbiakban:
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 } }a névnek
Akét lehetséges jelentése van a második névtér törzsében, mivel az osztályAés a használó aliasAis hatókörben van. Ezért a minősített névAhasználataA.Streamnem egyértelmű, és fordítási idő hibát okoz. A minősítő használataA::azonban nem hiba, mertAcsak névtér-aliasként jelenik meg.záró példa
ECMA C# draft specification