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.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 using_directivenásledovanými nulou nebo jednou global_attributes následovanou nulou nebo více namespace_member_declarations. Compilation_unit definuje celkovou strukturu vstupu.
compilation_unit
: extern_alias_directive* using_directive* global_attributes?
namespace_member_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í using_directives, global_attributes a namespace_member_declarationtéto kompilační jednotky, ale nemají žádný vliv na jiné kompilační jednotky.
Using_directivekompilační jednotky ovlivňují global_attributes a namespace_member_declarations této kompilační jednotky, ale nemají žádný vliv na jiné kompilační jednotky.
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_declarationkaždé kompilační jednotky programu přispívají členy do jediného prostoru deklarace nazývaného globální obor názvů.
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.
namespace_declaration
: 'namespace' qualified_identifier namespace_body ';'?
;
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ů.
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.
Qualified_identifiernamespace_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
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
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 se vztahuje na using_directive, global_attributes a namespace_member_declarationjeho bezprostředně obsahující compilation_unit nebo namespace_body.
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 najdete v §14.5.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 Použití direktiv
14.5.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.5.2) zavádí alias oboru názvů nebo typu.
A using_namespace_directive (§14.5.3) importuje členy typu oboru názvů.
A using_static_directive (§14.5.4) importuje vnořené typy a statické členy typu.
Rozsah using_directive přesahuje namespace_member_declarations jeho bezprostředně obsahující kompilační jednotku nebo tělo oboru názvů. Rozsah using_directive konkrétně nezahrnuje jeho partnerský using_directives. Peer using_directivese tedy navzájem neovlivňují a pořadí, ve kterém jsou napsány, je nevýznamné. Naproti tomu rozsah extern_alias_directive zahrnuje using_directivedefinované ve stejné jednotce kompilace nebo oboru názvů.
14.5.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 v kvalifikovaném členu aliasu (§14.8), 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ů. 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, 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.5.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.5.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.5.3.
14.6 Deklarace členů oboru názvů
Namespace_member_declaration je namespace_declaration (§14.3) nebo type_declaration (§14.7).
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.7 Deklarace typů
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.8 Kvalifikovaný člen aliasu
14.8.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.5.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, není definována qualified_alias_member a dojde k chybě v době kompilace.
- Jinak pokud deklarace oboru názvů nebo kompilační jednotka obsahuje extern_alias_directive nebo using_alias_directive , které přidruží
Nk oboru názvů, 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ý
- 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.8.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