Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
14.1 Obecné
Programy v jazyce C# jsou uspořádány pomocí oborů názvů. Obory názvů se používají jako "interní" organizační systém pro program a jako "externí" organizační systém – způsob prezentace prvků programu, které jsou vystavené jiným programům.
Použití direktiv (§14.6) a globálních direktiv using (§14.5) je poskytováno pro usnadnění používání oborů názvů.
14.2 Jednotky kompilace
Compilation_unit se skládá z nuly nebo více extern_alias_directivenásledovaných nulou nebo více global_using_directivenásledovanými nulou nebo více using_directivenásledovanými nulou nebo jedním global_attributes následovaným compilation_unit_body. Compilation_unit_body může být nula nebo více statement_listnásledovaných nulou nebo více namespace_member_declarationnebo file_scoped_namespace_declaration. Compilation_unit definuje celkovou strukturu vstupu.
compilation_unit
: extern_alias_directive* using_directive* global_attributes? compilation_unit_body
;
compilation_unit_body
: statement_list* namespace_member_declaration*
| file_scoped_namespace_declaration
;
Program jazyka C# se skládá z jedné nebo více jednotek kompilace. Při kompilaci programu jazyka C# se všechny kompilační jednotky zpracovávají společně. Kompilační jednotky tedy mohou záviset na sobě navzájem, pravděpodobně cyklický.
Extern_alias_directivekompilační jednotky ovlivňují global_using_directives, using_directives, global_attributes a compilation_unit_body této kompilační jednotky, ale nemají žádný vliv na jiné kompilační jednotky.
Using_directivekompilační jednotky ovlivňují global_attributes a compilation_unit_body této kompilační jednotky, ale nemají žádný vliv na jiné kompilační jednotky.
Global_using_directivekompilační jednotky ovlivňují global_attributes a namespace_member_declarationvšech jednotek kompilace v programu.
Global_attributes (§23.3) kompilační jednotky umožňují specifikaci atributů pro cílové sestavení a modul. Sestavení a moduly fungují jako fyzické kontejnery pro typy. Sestavení se může skládat z několika fyzicky samostatných modulů.
Namespace_member_declarations nebo file_scoped_namespace_declaration každé kompilační jednotky programu přispívají členy do jediného prostoru deklarace označovaného jako globální obor názvů.
File_scoped_namespace_declaration přispívá členům odpovídajícím namespace_declaration, kterým je séanticky ekvivalentní (§14.3).
Example:
// File A.cs: class A {} // File B.cs: class B {}Tyto dvě kompilační jednotky přispívají k jednomu globálnímu oboru názvů, v tomto případě deklarují dvě třídy s plně kvalifikovanými názvy
AaB. Vzhledem k tomu, že tyto dvě kompilační jednotky přispívají ke stejnému prostoru deklarace, byla by chyba, pokud by každá obsahovala deklaraci člena se stejným názvem.konec příkladu
14.3 Deklarace oboru názvů
Namespace_declaration se skládá z oboru názvů klíčových slov, za kterým následuje název oboru názvů a text, volitelně následovaný středníkem.
File_scoped_namespace_declaration se skládá z klíčového slova namespace, následovaného názvem oboru názvů, středníkem a volitelným seznamem extern_alias_directives, using_directives a type_declarations.
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* '}'
;
Namespace_declaration může dojít jako deklarace nejvyšší úrovně v compilation_unit nebo jako deklarace člena v rámci jiného namespace_declaration. Když namespace_declaration dojde v compilation_unit jako deklarace nejvyšší úrovně, stane se obor názvů členem globálního oboru názvů. Když namespace_declaration dojde v jiné namespace_declaration, vnitřní obor názvů se stane členem vnějšího oboru názvů. V obou případech musí být název oboru názvů jedinečný v rámci obsahujícího oboru názvů.
File_scoped_namespace_declaration může nastat pouze jako deklarace nejvyšší úrovně v compilation_unit. Deklarovaný obor názvů se tak stane členem globálního oboru názvů.
Obory názvů jsou implicitně public a deklarace oboru názvů nemůže obsahovat žádné modifikátory přístupu.
V rámci namespace_body volitelná using_directivenaimportují názvy jiných oborů názvů, typů a členů, které umožňují odkazovat přímo místo kvalifikovaných názvů. Volitelné namespace_member_declarationpřispívají členy do prostoru deklarace oboru názvů. Všimněte si, že všechny using_directivemusí být uvedeny před prohlášením o členech.
V rámci file_scoped_namespace_declaration nepovinný using_directiveimportuje názvy jiných oborů názvů, typů a členů, což jim umožňuje odkazovat přímo místo kvalifikovaných názvů. Volitelné type_declarationpřispívají členy do prostoru deklarace oboru názvů. Všimněte si, že všechny using_directivemusí být uvedeny před všemi prohlášeními o typu.
Qualified_identifiernamespace_declaration a file_scoped_namespace_declaration může být jeden identifikátor nebo posloupnost identifikátorů oddělených tokeny ".". Druhý formulář umožňuje programu definovat vnořený obor názvů bez lexikálního vnoření několika deklarací oboru názvů.
Example:
namespace N1.N2 { class A {} class B {} }je sémanticky ekvivalentní
namespace N1 { namespace N2 { class A {} class B {} } }konec příkladu
File_scoped_namespace_declaration umožňuje zápis deklarace oboru názvů bez doprovodného { … } bloku.
Example:
namespace Name; using System; class C { }je sémanticky ekvivalentní
namespace Name { using System; class C { } }konec příkladu
File_scoped_namespace_declaration se považuje za namespace_declaration ve stejném umístění ve compilation_unit se stejným qualified_identifier. Extern_alias_directive, using_directives a type_declarationtohoto file_scoped_namespace_declaration fungují stejně, jako by byly deklarovány ve stejném pořadí uvnitř namespace_body tohoto namespace_declaration.
Poznámka: Podle gramatiky nemůže jednotka kompilace obsahovat file_scoped_namespace_declaration i namespace_declaration. Nesmí obsahovat více file_scoped_namespace_declarations. Nemůže obsahovat file_scoped_namespace_declaration ani žádné příkazynejvyšší úrovně. type_declarationnemůže předcházet file_scoped_namespace_declaration. koncová poznámka
Různé kompilační jednotky můžou přispívat do stejného oboru názvů pomocí namespace_member_declaration nebofile_scoped_namespace_declaration syntaxe .
Obory názvů jsou otevřené a dvě deklarace oboru názvů se stejným plně kvalifikovaným názvem (§7.8.3) přispívají do stejného prostoru deklarace (§7.3).
Příklad: V následujícím kódu
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }dvě deklarace oboru názvů výše přispívají ke stejnému prostoru deklarace, v tomto případě deklarují dvě třídy s plně kvalifikovanými názvy
N1.N2.AaN1.N2.B. Vzhledem k tomu, že dvě deklarace přispívají ke stejnému prostoru deklarace, byla by chyba, pokud každá deklarace člena se stejným názvem.konec příkladu
File_scoped_namespace_declaration umožňuje zápis deklarace oboru názvů bez doprovodného { … } bloku.
Example:
namespace Name; using System; class C { }je sémanticky ekvivalentní
namespace Name { using System; class C { } }konec příkladu
File_scoped_namespace_declaration se považuje za namespace_declaration ve stejném umístění ve compilation_unit se stejným qualified_identifier. Extern_alias_directive, using_directives a type_declarationtohoto file_scoped_namespace_declaration fungují stejně, jako by byly deklarovány ve stejném pořadí uvnitř namespace_body tohoto namespace_declaration.
Poznámka: Podle gramatiky nemůže jednotka kompilace obsahovat file_scoped_namespace_declaration i namespace_declaration. Nesmí obsahovat více file_scoped_namespace_declarations. Nemůže obsahovat file_scoped_namespace_declaration ani žádné příkazynejvyšší úrovně. type_declarationnemůže předcházet file_scoped_namespace_declaration. koncová poznámka
Různé kompilační jednotky můžou přispívat do stejného oboru názvů pomocí namespace_member_declaration nebofile_scoped_namespace_declaration syntaxe .
14.4 Direktivy extern aliasů
Extern_alias_directive zavádí identifikátor, který slouží jako alias oboru názvů. Specifikace aliasovaného oboru názvů je externí pro zdrojový kód programu a vztahuje se také na vnořené obory názvů aliasovaného oboru názvů.
extern_alias_directive
: 'extern' 'alias' identifier ';'
;
Rozsah extern_alias_directive je popsán v §7.7.1.
V rámci kompilační jednotky nebo těla oboru názvů, který obsahuje extern_alias_directive, lze identifikátor zavedený extern_alias_directive použít k odkazování na aliasovaný obor názvů. Jedná se o chybu v době kompilace, aby identifikátor byl slovo global.
Alias zavedený extern_alias_directive je velmi podobný aliasu zavedenému using_alias_directive. Podrobnější informace o extern_alias_directives a using_alias_directives naleznete v §14.6.2.
alias je kontextové klíčové slovo (§6.4.4) a má zvláštní význam pouze tehdy, když bezprostředně následuje extern klíčové slovo v extern_alias_directive.
K chybě dojde, pokud program deklaruje extern alias, pro který není k dispozici žádná externí definice.
Příklad: Následující program deklaruje a používá dva extern aliasy a
XYkaždý z nich představuje kořen jedinečné hierarchie oborů názvů:extern alias X; extern alias Y; class Test { X::N.A a; X::N.B b1; Y::N.B b2; Y::N.C c; }Program deklaruje existenci extern aliasů
XaY, ale skutečné definice aliasů jsou pro program vnější. Identické pojmenovanéN.Btřídy lze nyní odkazovat jakoX.N.BaY.N.B, nebo pomocí kvalifikátorX::N.Baliasu oboru názvů aY::N.B. konec příkladu
14.5 Globální direktivy using
14.5.1 Obecné
Globální direktiva using je direktiva using (§14.6) na nejvyšší úrovni kompilační jednotky.
global_using_directive
: global_using_alias_directive
| global_using_namespace_directive
| global_using_static_directive
;
Poznámka: Rozsah global_using_directive se vztahuje na namespace_member_declarationvšech jednotek kompilace v programu. Rozsah global_using_directive konkrétně nezahrnuje jiné global_using_directives. Proto peer global_using_directives nebo ty z jiné kompilační jednotky nemají vliv na sebe navzájem a pořadí, ve kterém jsou zapsány, je zanedbatelné. Rozsah global_using_directive konkrétně nezahrnuje using_directiveokamžitě obsažené v žádné kompilační jednotce programu.
Účinek přidání global_using_directive do programu lze považovat za účinek přidání podobného using_directive , který se přeloží na stejný cílový obor názvů nebo typ na každou kompilační jednotku programu. Cíl global_using_directive je však vyřešen v kontextu kompilační jednotky, která ji obsahuje. koncová poznámka
14.5.2 Global using alias direktivy
Global_using_alias_directive zavádí identifikátor, který slouží jako alias pro obor názvů nebo typ v rámci programu.
global_using_alias_directive
: 'global' using_alias_directive
;
V rámci deklarací členů v libovolné kompilační jednotce programu, který obsahuje global_using_alias_directive, lze identifikátor zavedený global_using_alias_directive použít k odkazování na daný obor názvů nebo typ.
Identifikátorglobal_using_alias_directive musí být jedinečný v prostoru deklarace jakékoli kompilační jednotky programu, který obsahuje global_using_alias_directive.
Stejně jako běžné členy jsou názvy zavedené global_using_alias_directives skryté podobnými pojmenovanými členy v vnořených oborech.
Pořadí, ve kterém jsou global_using_alias_directivezapsány, nemá žádný význam a řešení namespace_or_type_name odkazovaného global_using_alias_directive není ovlivněno global_using_alias_directive samotným nebo jinými global_using_directives nebo using_directivev programu. Jinými slovy, namespace_or_type_nameglobal_using_alias_directive se vyřeší, jako by okamžitě obsahující kompilační jednotka neměla žádné using_directives a celý program obsahující program neměl žádné global_using_directives. Global_using_alias_directive však mohou být ovlivněny extern_alias_directives v bezprostředně obsahující kompilační jednotce.
Global_using_alias_directive může vytvořit alias pro libovolný obor názvů nebo typ.
Přístup k oboru názvů nebo typu prostřednictvím aliasu poskytuje přesně stejný výsledek jako přístup k danému oboru názvů nebo typu prostřednictvím deklarovaného názvu.
Použití aliasů může pojmenovat uzavřený vytvořený typ, ale nemůže pojmenovat nevázanou deklaraci obecného typu bez zadání argumentů typu.
14.5.3 Global using namespace direktivy
Global_using_namespace_directive importuje typy obsažené v oboru názvů do programu, což umožňuje použití identifikátoru každého typu bez kvalifikace.
global_using_namespace_directive
: 'global' using_namespace_directive
;
V rámci deklarací členů v programu, který obsahuje global_using_namespace_directive, lze na typy obsažené v daném oboru názvů odkazovat přímo.
Global_using_namespace_directive importuje typy obsažené v daném oboru názvů, ale konkrétně neimportuje vnořené obory názvů.
Na rozdíl od global_using_alias_directive může global_using_namespace_directive importovat typy, jejichž identifikátory jsou již definovány v kompilační jednotce programu. V dané jednotce kompilace jsou názvy importované všemi global_using_namespace_directive v programu skryty podobnými pojmenovanými členy v kompilační jednotce.
Pokud více než jeden obor názvů nebo typ importovaný global_using_namespace_directives nebo global_using_static_directiveve stejném programu obsahuje typy se stejným názvem, odkazy na tento název jako type_name jsou považovány za nejednoznačné.
Navíc pokud více než jeden obor názvů nebo typ importovaný global_using_namespace_directives nebo global_using_static_directiveve stejném programu obsahuje typy nebo členy se stejným názvem, odkazy na tento název jako simple_name jsou považovány za nejednoznačné.
Namespace_name odkazované global_using_namespace_directive se řeší stejným způsobem jako namespace_or_type_name odkazované global_using_alias_directive. Proto global_using_namespace_directiveve stejném programu navzájem neovlivňují a mohou být zapsány v libovolném pořadí.
14.5.4 Global using static direktivy
Global_using_static_directive importuje vnořené typy a statické členy obsažené přímo v deklaraci typu do programu obsahujícího, což umožňuje použít identifikátor každého člena a typu bez kvalifikace.
global_using_static_directive
: 'global' using_static_directive
;
V rámci deklarací členů v programu, který obsahuje global_using_static_directive, lze přímo odkazovat na přístupné vnořené typy a statické členy (s výjimkou rozšiřujících metod) obsažené přímo v deklaraci daného typu.
Global_using_static_directive konkrétně neimportuje rozšiřující metody přímo jako statické metody, ale zpřístupňuje je pro vyvolání metody rozšíření.
Global_using_static_directive importuje pouze členy a typy deklarované přímo v daném typu, nikoli členy a typy deklarované v základních třídách.
Nejednoznačnosti mezi více global_using_namespace_directives a global_using_static_directives jsou popsány v §14.5.3.
14.6 Použití direktiv
14.6.1 Obecné
Direktiva using usnadňuje použití oborů názvů a typů definovaných v jiných oborech názvů. Použití direktiv ovlivňuje proces překladu názvů namespace_or_type_names (§7.8) a simple_name(§12.8.4), ale na rozdíl od deklarací using_directive nepřispívají novým členům do podkladových prostorů deklarací jednotek kompilace nebo oborů názvů, vekterých se používají.
using_directive
: using_alias_directive
| using_namespace_directive
| using_static_directive
;
Using_alias_directive (§14.6.2) představuje alias oboru názvů nebo typu.
A using_namespace_directive (§14.6.3) importuje členy typu oboru názvů.
A using_static_directive (§14.6.4) importuje vnořené typy a statické členy typu.
Rozsah using_directive je popsán v §7.7.1.
14.6.2 Použití direktiv aliasů
Using_alias_directive zavádí identifikátor, který slouží jako alias pro obor názvů nebo typ v rámci bezprostředně ohraničující kompilační jednotku nebo tělo oboru názvů.
using_alias_directive
: 'using' identifier '=' namespace_or_type_name ';'
;
V rámci globálních atributů a deklarací členů v kompilační jednotce nebo těle oboru názvů, který obsahuje using_alias_directive, lze identifikátor zavedený using_alias_directive použít k odkazování na daný obor názvů nebo typ.
Example:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }Výše v rámci deklarací členů v oboru názvů
N3je alias proA, a proto třídaN1.N2.Aodvozena od třídyN3.B.N1.N2.AStejný účinek lze získat vytvořením aliasuRproN1.N2a následným odkazemR.A:namespace N3 { using R = N1.N2; class B : R.A {} }konec příkladu
V rámci direktiv using lze globální atributy a deklarace členů v jednotce kompilace nebo těle oboru názvů, které obsahují extern_alias_directive, identifikátor zavedený extern_alias_directive použít k odkazování na přidružený obor názvů.
Příklad: Příklad:
namespace N1 { extern alias N2; class B : N2::A {} }Výše je v rámci deklarací členů v
N1oboru názvů alias pro určitý obor názvů,N2jehož definice je externí ke zdrojovému kódu programu. TřídaN1.Bje odvozena od třídyN2.A. Stejný účinek lze získat vytvořením aliasuAproN2.Aa následným odkazemA:namespace N1 { extern alias N2; using A = N2::A; class B : A {} }konec příkladu
Extern_alias_directive nebo using_alias_directive zpřístupňuje alias v rámci konkrétní jednotky kompilace nebo těla oboru názvů, ale nepřispívá k podkladovému prostoru deklarace žádné nové členy. Jinými slovy, direktiva aliasu není tranzitivní, ale spíše ovlivňuje pouze kompilační jednotku nebo tělo oboru názvů, ve kterém se vyskytuje.
Příklad: V následujícím kódu
namespace N3 { extern alias R1; using R2 = N1.N2; } namespace N3 { class B : R1::A, R2.I {} // Error, R1 and R2 unknown }obory direktiv aliasů, které zavádějí
R1aR2rozšiřují pouze na deklarace členů v těle oboru názvů, ve kterém jsou obsaženy, takžeR1aR2jsou neznámé ve druhé deklaraci oboru názvů. Umístění direktiv aliasů do obsahující kompilační jednotky však způsobí, že alias bude k dispozici v rámci obou deklarací oboru názvů:extern alias R1; using R2 = N1.N2; namespace N3 { class B : R1::A, R2.I {} } namespace N3 { class C : R1::A, R2.I {} }konec příkladu
Každý extern_alias_directive nebo using_alias_directive v compilation_unit nebo namespace_body přispívá názvem do prostoru deklarace aliasu (§7.3) bezprostředně uzavřeného compilation_unit nebo namespace_body. Identifikátor směrnice aliasu musí být jedinečný v rámci odpovídajícího prostoru deklarace aliasu. Identifikátor aliasu nemusí být jedinečný v rámci globálního prostoru deklarace nebo prostoru deklarace odpovídajícího oboru názvů.
Example:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // OkPoužití pojmenovaného
Xaliasu způsobí chybu, protože už existuje alias pojmenovanýXve stejné jednotce kompilace. Pojmenovaná třídaYnení v konfliktu s externím aliasem pojmenovanýmY, protože tyto názvy jsou přidány do odlišných prostorů deklarací. První se přidá do globálního prostoru deklarace a druhý se přidá do prostoru deklarace aliasu pro tuto kompilační jednotku.Pokud název aliasu odpovídá názvu člena oboru názvů, musí být použití některého z těchto názvů odpovídajícím způsobem kvalifikované:
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 }Ve druhém těle oboru názvů pro
N3nekvalifikované použitíBvýsledků v důsledku chyby, protožeN3obsahuje člen pojmenovanýBa tělo oboru názvů, které také deklaruje alias s názvemB; podobně proA. Na tříduN3.Blze odkazovat jakoN3.Bneboglobal::N3.B. AliasAlze použít u člena kvalifikovaného aliasu (§14.9), napříkladA::B. AliasBje v podstatě zbytečný. Nelze jej použít v qualified_alias_member , protože v qualified_alias_member aBaliasech typu je možné použít pouze aliasy oboru názvů.konec příkladu
Stejně jako běžné členy jsou názvy zavedené alias_directives skryté podobnými pojmenovanými členy v vnořených oborech.
Příklad: V následujícím kódu
using R = N1.N2; namespace N3 { class R {} class B: R.A {} // Error, R has no member A }odkaz na
R.Adeklaraci příčin chyby v době kompilace, protožeBodkazuje naR, nikoliN3.RN1.N2.konec příkladu
Pořadí, ve kterém jsou zapsány extern_alias_directives, nemá význam. Pořadí, ve kterém jsou zapsány using_alias_directives, nemá žádný význam, ale všechny using_alias_directives po všech extern_alias_directives ve stejné kompilační jednotce nebo názvovém prostoru. Řešení namespace_or_type_name odkazované using_alias_directive není ovlivněno samotným using_alias_directive nebo jinými using_directivev bezprostředně obsahující kompilační jednotce nebo těle oboru názvů, ale může být ovlivněno extern_alias_directives v bezprostředně obsahující kompilační jednotce nebo těle oboru názvů. A pokud using_alias_directive je okamžitě obsažena v kompilační jednotce, není ovlivněna global_using_directivev programu. Jinými slovy, namespace_or_type_nameusing_alias_directive se vyřeší, jako by bezprostředně obsahující kompilační jednotku nebo tělo oboru názvů nemělo žádné using_directives a pokud using_alias_directive je okamžitě obsažen v kompilační jednotce, program neměl žádné global_using_directives, ale má správnou sadu extern_alias_directives.
Příklad: V následujícím kódu
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 }poslední using_alias_directive způsobí chybu v době kompilace, protože předchozí using_alias_directive to neovlivní. První using_alias_directive nemá za následek chybu, protože rozsah externího aliasu X zahrnuje using_alias_directive.
konec příkladu
Using_alias_directive může vytvořit alias pro libovolný obor názvů nebo typ, včetně oboru názvů, ve kterém se zobrazí, a libovolného oboru názvů nebo typu vnořeného v daném oboru názvů.
Přístup k oboru názvů nebo typu prostřednictvím aliasu poskytuje přesně stejný výsledek jako přístup k danému oboru názvů nebo typu prostřednictvím deklarovaného názvu.
Příklad: Dané
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 } }názvy
N1.N2.A,R1.N2.AaR2.Ajsou ekvivalentní a všechny odkazují na deklaraci třídy, jejíž plně kvalifikovaný název jeN1.N2.A.konec příkladu
I když je každá část částečného typu (§15.2.7) deklarována ve stejném oboru názvů, části se obvykle zapisují do různých deklarací oboru názvů. Proto mohou být pro každou část přítomny různé extern_alias_directives a using_directive. Při interpretaci jednoduchých názvů (§12.8.4) v rámci jedné části se považují pouze extern_alias_directives a using_directiveorgánů oboru názvů a kompilační jednotky ohraničující tuto část. To může mít za následek, že stejný identifikátor má různé významy v různých částech.
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 } }konec příkladu
Použití aliasů může pojmenovat uzavřený vytvořený typ, ale nemůže pojmenovat nevázanou deklaraci obecného typu bez zadání argumentů typu.
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 }konec příkladu
14.6.3 Použití direktiv oborů názvů
Using_namespace_directive importuje typy obsažené v oboru názvů do bezprostředně uzavřené kompilační jednotky nebo těla oboru názvů, což umožňuje použít identifikátor každého typu bez kvalifikace.
using_namespace_directive
: 'using' namespace_name ';'
;
V rámci deklarací členů v kompilační jednotce nebo těle oboru názvů, který obsahuje using_namespace_directive, lze odkazovat přímo na typy obsažené v daném oboru názvů.
Example:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }Výše v rámci deklarací členů v
N3oboru názvů jsou členyN1.N2typu přímo k dispozici, a proto třídaN3.Bje odvozena od třídyN1.N2.A.konec příkladu
Using_namespace_directive importuje typy obsažené v daném oboru názvů, ale konkrétně neimportuje vnořené obory názvů.
Příklad: V následujícím kódu
namespace N1.N2 { class A {} } namespace N3 { using N1; class B : N2.A {} // Error, N2 unknown }using_namespace_directive importuje typy obsažené v
N1, ale ne obory názvů vnořené doN1. Odkaz naN2.AdeklaraciBvýsledků tedy způsobí chybu v době kompilace, protože žádné členy pojmenovanéN2nejsou v oboru.konec příkladu
Na rozdíl od using_alias_directivemůže using_namespace_directive importovat typy, jejichž identifikátory jsou již definovány v rámci nadřazené kompilační jednotky nebo těla oboru názvů. V důsledku toho jsou názvy importované using_namespace_directive skryty podobnými pojmenovanými členy v ohraničující kompilační jednotce nebo textu oboru názvů.
Example:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }Zde v rámci deklarací členů v
N3oboru názvůAodkazujeN3.Aspíše nežN1.N2.Ana .konec příkladu
Vzhledem k tomu, že názvy mohou být nejednoznačné, když více než jeden importovaný obor názvů zavádí stejný název typu , je using_alias_directive užitečné k nejednoznačnosti odkazu.
Příklad: V následujícím kódu
namespace N1 { class A {} } namespace N2 { class A {} } namespace N3 { using N1; using N2; class B : A {} // Error, A is ambiguous }a
N1N2obsahují členaAa protožeN3importuje obojí, odkazováníAvN3je chyba v době kompilace. V této situaci lze konflikt vyřešit buď prostřednictvím kvalifikace odkazů naA, nebo zavedením using_alias_directive , který vybere konkrétníA. Například:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }konec příkladu
Kromě toho platí, že pokud více než jeden obor názvů nebo typ importovaný using_namespace_directives nebo using_static_directiveve stejné jednotce kompilace nebo těle oboru názvů obsahuje typy nebo členy se stejným názvem, odkazy na tento název jako simple_name jsou považovány za nejednoznačné.
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 } } }
N1obsahuje členAtypu aCobsahuje statické poleA, a protožeN2importuje obojí, odkazováníAjako simple_name je nejednoznačné a chyba v době kompilace.konec příkladu
Podobně jako using_alias_directiveusing_namespace_directive nepřispívá žádné nové členy do podkladového prostoru deklarace kompilační jednotky nebo oboru názvů, ale spíše ovlivňuje pouze kompilační jednotku nebo tělo oboru názvů, ve kterém se zobrazuje.
Namespace_name odkazované using_namespace_directive se řeší stejným způsobem jako namespace_or_type_name odkazované using_alias_directive. Proto using_namespace_directive s ve stejné kompilačníjednotce nebo těle oboru názvů navzájem neovlivňují a lze je zapsat v libovolném pořadí.
14.6.4 Použití statických direktiv
Using_static_directive importuje vnořené typy a statické členy obsažené přímo v deklaraci typu do bezprostředně uzavřené kompilační jednotky nebo těla oboru názvů, což umožňuje použít identifikátor každého člena a typu bez kvalifikace.
using_static_directive
: 'using' 'static' type_name ';'
;
V rámci deklarací členů v kompilační jednotce nebo těle oboru názvů, které obsahují using_static_directive, lze přímo odkazovat na přístupné vnořené typy a statické členy (s výjimkou rozšiřujících metod) obsažené přímo v deklaraci daného typu.
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(); } } }V předchozím kódu jsou v rámci deklarací členů v
N2oboru názvů statické členy a vnořené typyN1.Apřímo k dispozici, a proto metodaNmůže odkazovat jak naBMčlenyN1.A.konec příkladu
Using_static_directive konkrétně neimportuje rozšiřující metody přímo jako statické metody, ale zpřístupňuje je pro vyvolání rozšiřující metody (§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 importuje rozšiřující metodu
Mobsaženou vN1.A, ale pouze jako rozšiřující metodu. Proto první odkaz naMtextB.Nvýsledků v době kompilace chyba, protože žádné členy pojmenovanéMnejsou v oboru.konec příkladu
Using_static_directive importuje pouze členy a typy deklarované přímo v daném typu, nikoli členy a typy deklarované v základních třídách.
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 importuje metodu
M2obsaženou vN1.B, ale nenaimportuje metoduMobsaženou vN1.A. Proto odkaz naMtextC.Nvýsledků v době kompilace chyba, protože žádné členy pojmenovanéMnejsou v oboru. Vývojáři musí přidat druhouusing staticdirektivu, aby určili, že se mají importovat i metodyN1.A.konec příkladu
Nejednoznačnosti mezi více using_namespace_directives a using_static_directives jsou popsány v §14.6.3.
14.7 Deklarace členů oboru názvů
Namespace_member_declaration je namespace_declaration (§14.3) nebo type_declaration (§14.8).
namespace_member_declaration
: namespace_declaration
| type_declaration
;
Kompilační jednotka nebo tělo oboru názvů může obsahovat namespace_member_declarations a tyto deklarace přispívají novým členům do podkladového prostoru deklarace obsahující kompilační jednotky nebo těla oboru názvů.
14.8 Deklarace typu
Type_declaration je class_declaration (§15.2), struct_declaration (§16.2), interface_declaration (§19.2), enum_declaration (§20.2) nebo delegate_declaration (§21.2).
type_declaration
: class_declaration
| struct_declaration
| interface_declaration
| enum_declaration
| delegate_declaration
;
K type_declaration může dojít jako deklarace nejvyšší úrovně v kompilační jednotce nebo jako deklarace člena v rámci oboru názvů, třídy nebo struktury.
Pokud deklarace typu pro typ T nastane jako deklarace nejvyšší úrovně v kompilační jednotce, plně kvalifikovaný název (§7.8.3) deklarace typu je stejný jako nekvalifikovaný název deklarace (§7.8.2). Pokud deklarace typu pro typ T nastane v rámci deklarace oboru názvů, třídy nebo struktury, plně kvalifikovaný název (§7.8.3) deklarace typu je S.N, kde S je plně kvalifikovaný název obsahující obor názvů, třídy nebo deklarace struktury a N je nekvalifikovaný název deklarace.
Typ deklarovaný v rámci třídy, rozhraní nebo struktury se nazývá vnořený typ (§15.3.9).
Povolené modifikátory přístupu a výchozí přístup pro deklaraci typu závisí na kontextu, ve kterém se deklarace provádí (§7.5.2):
- Typy deklarované v jednotkách kompilace nebo oborech názvů mohou mít
publicnebointernalmají přístup. Výchozí hodnota jeinternalpřístup. - Typy deklarované ve třídách mohou mít
public, ,protected internalprotected,private protected, ,internal, neboprivatepřístup. Výchozí hodnota jeprivatepřístup. - Typy deklarované ve strukturách mohou mít
public,internalneboprivatepřístup. Výchozí hodnota jeprivatepřístup.
14.9 Kvalifikovaný člen aliasu
14.9.1 Obecné
Kvalifikátor :: aliasu oboru názvů umožňuje zaručit, že vyhledávání názvů typů není ovlivněno zavedením nových typů a členů. Kvalifikátor aliasu oboru názvů se vždy zobrazuje mezi dvěma identifikátory, které se označují jako identifikátory vlevo a zprava. Na rozdíl od běžného . kvalifikátoru se levý identifikátor kvalifikátoru :: vyhledá pouze jako extern nebo pomocí aliasu.
Qualified_alias_member poskytuje explicitní přístup k globálnímu oboru názvů a externímu oboru názvů nebo používání aliasů, které jsou potenciálně skryté jinými entitami.
qualified_alias_member
: identifier '::' identifier type_argument_list?
;
Qualified_alias_member lze použít jako namespace_or_type_name (§7.8) nebo jako levý operand v member_access (§12.8.7).
Qualified_alias_member se skládá ze dvou identifikátorů, označovaných jako identifikátory vlevo a zprava, které jsou označeny tokenem::, a volitelně následuje type_argument_list. Pokud je identifikátor vlevo globální, globální obor názvů se vyhledá pro identifikátor pravé ruky. U jakéhokoli jiného levého identifikátoru se tento identifikátor vyhledá jako extern nebo používá alias (§14.4 a §14.6.2). K chybě v době kompilace dochází v případě, že neexistuje žádný takový alias nebo alias odkazuje na typ. Pokud alias odkazuje na obor názvů, vyhledá se v daném oboru názvů pravý identifikátor.
Qualified_alias_member má jednu ze dvou forem:
-
N::I<A₁, ..., Aₑ>, kdeNaIpředstavuje identifikátory a<A₁, ..., Aₑ>je seznam argumentů typu. (eje vždy alespoň jedna.) -
N::I, kdeNaIpředstavuje identifikátory. (V tomto případěese považuje za nulu.)
Při tomto zápisu je význam qualified_alias_member určen takto:
- Pokud
Nse jedná o identifikátorglobal, vyhledá seIglobální obor názvů:- Pokud globální obor názvů obsahuje obor názvů s názvem
Inulae, qualified_alias_member odkazuje na tento obor názvů. - V opačném případě, pokud globální obor názvů obsahuje ne generický typ pojmenovaný
Iaeje nula, qualified_alias_member odkazuje na tento typ. - Pokud globální obor názvů obsahuje typ s názvem
Ies parametry typu, qualified_alias_member odkazuje na tento typ vytvořený s danými argumenty typu. - V opačném případě je qualified_alias_member nedefinovaný a dojde k chybě v době kompilace.
- Pokud globální obor názvů obsahuje obor názvů s názvem
- Jinak počínaje prohlášením oboru názvů (§14.3) bezprostředně obsahujícím qualified_alias_member (pokud existuje), pokračujeme s každou uzavřenou deklarací oboru názvů (pokud existuje) a končící jednotkou kompilace obsahující qualified_alias_member, budou následující kroky vyhodnoceny, dokud se nenachází entita:
- Pokud deklarace oboru názvů nebo kompilační jednotka obsahuje using_alias_directive , která přidruží N k typu, nebo když je dosažena kompilační jednotka, program obsahuje global_using_alias_directive , které přidruží
Nk typu, pak qualified_alias_member není definována a dojde k chybě kompilace. - Jinak pokud deklarace oboru názvů nebo kompilační jednotka obsahuje extern_alias_directive nebo using_alias_directive, které přidruží k oboru názvů nebo když je dosažena kompilační jednotka, program obsahuje global_using_alias_directive, které přidruží
NNk oboru názvů, a pak:- Pokud obor názvů přidružený
Nobsahuje názevIoboru názvů aeje nula, qualified_alias_member odkazuje na tento obor názvů. - V opačném případě pokud obor názvů přidružený
Nobsahuje ne generický typ s názvemIaeje nula, qualified_alias_member odkazuje na tento typ. - Jinak pokud obor názvů přidružený
Nobsahuje typ s názvemIseparametry typu, qualified_alias_member odkazuje na tento typ vytvořený s danými argumenty typu. - V opačném případě je qualified_alias_member nedefinovaný a dojde k chybě v době kompilace.
- Pokud obor názvů přidružený
- Pokud deklarace oboru názvů nebo kompilační jednotka obsahuje using_alias_directive , která přidruží N k typu, nebo když je dosažena kompilační jednotka, program obsahuje global_using_alias_directive , které přidruží
- V opačném případě je qualified_alias_member nedefinovaný a dojde k chybě v době kompilace.
Příklad: V kódu:
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; } }třída
Aje odkazována sglobal::Aa typSystem.Net.Sockets.Socketje odkazován sS::Socket. PoužitíA.xaS.Socketmísto toho by způsobilo chyby v době kompilace, protožeAbySse vyřešily parametry.konec příkladu
Poznámka: Identifikátor
globalmá zvláštní význam pouze v případech, kdy se používá jako levý identifikátor qualified_alias_name. Není to klíčové slovo a není to sám alias; je kontextové klíčové slovo (§6.4.4). V kódu:class A { } class C { global.A x; // Error: global is not defined global::A y; // Valid: References A in the global namespace }použití
global.Azpůsobí chybu v době kompilace, protože v oboru neexistuje žádná entitaglobal. Pokud by některá entita s názvem global byla v oboru, přeložilaglobalglobal.Aby se na tuto entitu.Použití
globaljako identifikátor levé ruky qualified_alias_member vždy způsobí vyhledávání vglobaloboru názvů, i když existuje alias s názvemglobal. V kódu: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.Apřekládá aMyGlobalTypes.Aglobal::Apřekládá na tříduAv globálním oboru názvů.koncová poznámka
14.9.2 Jedinečnost aliasů
Každá jednotka kompilace a tělo oboru názvů má samostatný prostor deklarace pro extern aliasy a použití aliasů. I když je název externího aliasu nebo použití aliasu jedinečný v rámci sady externích aliasů a použití aliasů deklarovaných v bezprostředně obsahující kompilační jednotce nebo těle oboru názvů, může mít alias stejný název jako typ nebo obor názvů, pokud se používá pouze s kvalifikátorem :: .
Příklad: V následujícím příkladu:
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 } }název
Amá ve druhém těle oboru názvů dva možné významy, protožeAtřída i aliasAusing jsou v oboru. Z tohoto důvodu je použitíAv kvalifikovaném názvuA.Streamnejednoznačné a způsobuje chybu v době kompilace. PoužitíAs kvalifikátorem::však není chybou, protožeAse vyhledá pouze jako alias oboru názvů.konec příkladu
ECMA C# draft specification