14 Oborů názvů
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_directive kompilač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_directive kompilační jednotky ovlivňují global_attributes a namespace_member_declarationtéto kompilační jednotky, ale nemají žádný vliv na jiné kompilační jednotky.
Global_attributes (§22.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_declaration s každé kompilační jednotky programu přispívají členy do jediného prostoru deklarace nazývaného globální obor názvů.
Příklad:
// 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
A
aB
. 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.end example
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* '}'
;
K 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ě, obor názvů se stane členem globálního oboru názvů. Když dojde namespace_declaration v rámci jiného 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_directivese zobrazí před každou prohlášeními o členech.
Qualified_identifier 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ů.
Příklad:
namespace N1.N2 { class A {} class B {} }
je sémanticky ekvivalentní
namespace N1 { namespace N2 { class A {} class B {} } }
end example
Obory názvů jsou otevřené a dvě deklarace oboru názvů se stejným plně kvalifikovaným názvem (§7.8.2) 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.A
aN1.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.end example
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 představený 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.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
Y
X
kaž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ů
X
aY
, ale skutečné definice aliasů jsou pro program vnější. Identické pojmenovanéN.B
třídy lze nyní odkazovat jakoX.N.B
aY.N.B
, nebo pomocí kvalifikátorX::N.B
aliasu oboru názvů aY::N.B
. end example
14.5 Použití direktiv
14.5.1 Obecné
Použití direktiv 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_names (§12.8.4), ale na rozdíl od deklarací using_directivenepřispívá novým členům do podkladových prostorů deklarací jednotek kompilace nebo oborů názvů, ve který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 se vztahuje na 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_directive s. Peer using_directivese tedy navzájem neovlivňují a pořadí, ve kterém jsou napsány, je zanedbatelné. 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 oboru názvů nebo typu 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.
Příklad:
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ů
A
je alias proN1.N2.A
, a proto třídaN3.B
odvozena od třídyN1.N2.A
.N3
Stejný účinek lze získat vytvořením aliasuR
proN1.N2
a následným odkazemR.A
:namespace N3 { using R = N1.N2; class B : R.A {} }
end example
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
N1
oboru názvů alias pro určitý obor názvů,N2
jehož definice je externí ke zdrojovému kódu programu. TřídaN1.B
je odvozena od třídyN2.A
. Stejný účinek lze získat vytvořením aliasuA
proN2.A
a následným odkazemA
:namespace N1 { extern alias N2; using A = N2::A; class B : A {} }
end example
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á do podkladového 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í
R1
aR2
rozšiřují pouze na deklarace členů v těle oboru názvů, ve kterém jsou obsaženy, takžeR1
aR2
jsou 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 {} }
end example
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ů.
Příklad:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // Ok
Použití pojmenovaného
X
aliasu způsobí chybu, protože už existuje alias pojmenovanýX
ve stejné jednotce kompilace. Pojmenovaná třídaY
není 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
N3
nekvalifikované použitíB
výsledků v důsledku chyby, protožeN3
obsahuje člen pojmenovanýB
a tělo oboru názvů, které také deklaruje alias s názvemB
; podobně proA
. Na tříduN3.B
lze odkazovat jakoN3.B
neboglobal::N3.B
. AliasA
lze použít v kvalifikovaném členu aliasu (§14.8), napříkladA::B
. AliasB
je v podstatě zbytečný. Nelze jej použít v qualified_alias_member , protože v qualified_alias_member aB
aliasech typu je možné použít pouze aliasy oboru názvů.end example
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.A
deklaraci příčin chyby v době kompilace, protožeR
odkazuje naN3.R
, nikoliN1.N2
B
.end example
Pořadí, ve kterém jsou zapsány extern_alias_directive, nemá žádný 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_directive ve stejné kompilačníjednotce nebo názvovém prostoru. Řešení namespace_or_type_name odkazovaných using_alias_directive není ovlivněno samotným using_alias_directive nebo jinými using_directivev bezprostředně obsahujícím kompilační jednotku nebo tělo 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_name using_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.
end example
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.A
aR2.A
jsou ekvivalentní a všechny odkazují na deklaraci třídy, jejíž plně kvalifikovaný název jeN1.N2.A
.end example
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_directives těl 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.
Příklad:
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 } }
end example
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.
Příklad:
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 }
end example
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ů.
Příklad:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }
Výše v rámci deklarací členů v
N3
oboru názvů jsou členyN1.N2
typu přímo k dispozici, a proto třídaN3.B
je odvozena od třídyN1.N2.A
.end example
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.A
deklaraciB
výsledků tedy způsobí chybu v době kompilace, protože žádné členy pojmenovanéN2
nejsou v oboru.end example
Na rozdíl od using_alias_directive můž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 nadřazené jednotce kompilace nebo textu oboru názvů.
Příklad:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }
Zde v rámci deklarací členů v
N3
oboru názvůA
odkazujeN3.A
spíše nežN1.N2.A
na .end example
Vzhledem k tomu, že názvy můžou 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
N1
N2
obsahují členaA
a protožeN3
importuje obojí, odkazováníA
vN3
je 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
. Příklad:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }
end example
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ů obsahují typy nebo členy se stejným názvem, odkazy na tento název jako simple_name jsou považovány za nejednoznačné.
Příklad:
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 } } }
N1
obsahuje členA
typu aC
obsahuje statické poleA
a protožeN2
importuje obojí, odkazováníA
jako simple_name je nejednoznačné a chyba v době kompilace.end example
Podobně jako using_alias_directive using_namespace_directive nepřispívá žádné nové členy do podkladového prostoru deklarace kompilační jednotky nebo oboru názvů, ale ovlivňuje pouze kompilační jednotku nebo tělo oboru názvů, ve kterém se zobrazuje.
Namespace_name odkazovaná using_namespace_directive se vyřeší stejným způsobem jako namespace_or_type_name odkazovaná using_alias_directive. Proto using_namespace_directives ve stejné kompilační jednotce nebo těle oboru názvů nemají vliv na sebe 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ý obsahuje 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.
Příklad:
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
N2
oboru názvů statické členy a vnořené typyN1.A
přímo k dispozici, a proto metodaN
může odkazovat jak naB
M
členyN1.A
.end example
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.9.3).
Příklad:
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
M
obsaženou vN1.A
, ale pouze jako rozšiřující metodu. Proto první odkaz naM
textB.N
výsledků v době kompilace chyba, protože žádné členy pojmenovanéM
nejsou v oboru.end example
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.
Příklad:
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
M2
obsaženou vN1.B
, ale nenaimportuje metoduM
obsaženou vN1.A
. Proto odkaz naM
textC.N
výsledků v době kompilace chyba, protože žádné členy pojmenovanéM
nejsou v oboru. Vývojáři musí přidat druhouusing static
direktivu, aby určili, že se mají importovat i metodyN1.A
.end example
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 (§18.2), enum_declaration (§19.2) nebo delegate_declaration (§20.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.2) 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 S.N
typu , 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 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
public
nebointernal
mají přístup. Výchozí hodnota jeinternal
přístup. - Typy deklarované ve třídách mohou mít
public
, ,protected internal
protected
,private protected
, ,internal
, neboprivate
přístup. Výchozí hodnota jeprivate
přístup. - Typy deklarované ve strukturách mohou mít
public
,internal
neboprivate
přístup. Výchozí hodnota jeprivate
pří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 ke globálnímu oboru názvů a externímu oboru názvů nebo použití 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 zleva 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ₑ>
, kdeN
aI
představuje identifikátory a<A₁, ..., Aₑ>
je seznam argumentů typu. (e
je vždy alespoň jedna.)N::I
, kdeN
aI
představuje identifikátory. (V tomto případěe
se považuje za nulu.)
Při tomto zápisu je význam qualified_alias_member určen takto:
- Pokud
N
se jedná o identifikátorglobal
, vyhledá seI
globální obor názvů:- Pokud globální obor názvů obsahuje obor názvů s názvem
I
nulae
, 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ý
I
ae
je nula, qualified_alias_member odkazuje na tento typ. - Pokud globální obor názvů obsahuje typ s názvem
I
e
s 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čujte každou uzavřenou deklarací oboru názvů (pokud existuje) a končící jednotkou kompilace obsahující qualified_alias_member, následující kroky se vyhodnocují, 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ží
N
k oboru názvů, pak:- Pokud obor názvů přidružený
N
obsahuje názevI
oboru názvů ae
je nula, qualified_alias_member odkazuje na tento obor názvů. - V opačném případě, pokud obor názvů přidružený
N
obsahuje ne generický typ pojmenovanýI
ae
je nula, qualified_alias_member odkazuje na tento typ. - Jinak pokud obor názvů přidružený
N
obsahuje typ s názvemI
se
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 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
A
je odkazována sglobal::A
a typSystem.Net.Sockets.Socket
je odkazován sS::Socket
. PoužitíA.x
aS.Socket
místo toho by způsobilo chyby v době kompilace, protožeA
byS
se vyřešily parametry.end example
Poznámka: Identifikátor
global
má 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.A
způ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žilaglobal
global.A
by se na tuto entitu.Použití
global
jako identifikátoru levé strany qualified_alias_member vždy způsobí vyhledávání vglobal
oboru 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.A
překládá aMyGlobalTypes.A
global::A
překládá na tříduA
v 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
A
má ve druhém těle oboru názvů dva možné významy, protožeA
třída i aliasA
using jsou v oboru. Z tohoto důvodu je použitíA
v kvalifikovaném názvuA.Stream
nejednoznačné a způsobuje chybu v době kompilace. PoužitíA
s kvalifikátorem::
však není chybou, protožeA
se vyhledá pouze jako alias oboru názvů.end example
ECMA C# draft specification