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.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 A a B. 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.A a N1.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ů X a Y, ale skutečné definice aliasů jsou pro program vnější. Identické pojmenované N.B třídy lze nyní odkazovat jako X.N.B a Y.N.B, nebo pomocí kvalifikátor X::N.B aliasu oboru názvů a Y::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ů N3 je alias pro A, a proto třída N1.N2.A odvozena od třídy N3.B.N1.N2.A Stejný účinek lze získat vytvořením aliasu R pro N1.N2 a následným odkazem R.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 N1 oboru názvů alias pro určitý obor názvů, N2 jehož definice je externí ke zdrojovému kódu programu. Třída N1.B je odvozena od třídy N2.A. Stejný účinek lze získat vytvořením aliasu A pro N2.A a následným odkazem A:

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í R1 a R2 rozšiřují pouze na deklarace členů v těle oboru názvů, ve kterém jsou obsaženy, takže R1 a R2 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 {}
}

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 {} // Ok

Použití pojmenovaného X aliasu způsobí chybu, protože už existuje alias pojmenovaný X ve stejné jednotce kompilace. Pojmenovaná třída Y není v konfliktu s externím aliasem pojmenovaným Y , 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í B výsledků v důsledku chyby, protože N3 obsahuje člen pojmenovaný B a tělo oboru názvů, které také deklaruje alias s názvem B; podobně pro A. Na třídu N3.B lze odkazovat jako N3.B nebo global::N3.B. Alias A lze použít u člena kvalifikovaného aliasu (§14.9), například A::B. Alias B je v podstatě zbytečný. Nelze jej použít v qualified_alias_member , protože v qualified_alias_member a B aliasech 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.A deklaraci příčin chyby v době kompilace, protože B odkazuje na R, nikoli N3.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.Aa R2.A jsou ekvivalentní a všechny odkazují na deklaraci třídy, jejíž plně kvalifikovaný název je N1.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 N3 oboru názvů jsou členy N1.N2 typu přímo k dispozici, a proto třída N3.B je odvozena od třídy N1.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é do N1. Odkaz na N2.A deklaraci B výsledků tedy způsobí chybu v době kompilace, protože žádné členy pojmenované N2 nejsou 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 N3 oboru názvů A odkazuje N3.A spíš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 N1N2 obsahují člena Aa protože N3 importuje obojí, odkazování A v N3 je chyba v době kompilace. V této situaci lze konflikt vyřešit buď prostřednictvím kvalifikace odkazů na A, 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
        }
    }
}

N1 obsahuje člen Atypu a C obsahuje statické pole A, a protože N2 importuje obojí, odkazování A jako 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 N2 oboru názvů statické členy a vnořené typy N1.A přímo k dispozici, a proto metoda N může odkazovat jak na BM členy N1.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 M obsaženou v N1.A, ale pouze jako rozšiřující metodu. Proto první odkaz na M text B.N výsledků v době kompilace chyba, protože žádné členy pojmenované M nejsou 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 M2 obsaženou v N1.B, ale nenaimportuje metodu M obsaženou v N1.A. Proto odkaz na M text C.N výsledků v době kompilace chyba, protože žádné členy pojmenované M nejsou v oboru. Vývojáři musí přidat druhou using static direktivu, aby určili, že se mají importovat i metody N1.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 public nebo internal mají přístup. Výchozí hodnota je internal přístup.
  • Typy deklarované ve třídách mohou mít public, , protected internalprotected, private protected, , internal, nebo private přístup. Výchozí hodnota je private přístup.
  • Typy deklarované ve strukturách mohou mít public, internalnebo private přístup. Výchozí hodnota je private pří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ₑ>, kde N a I představuje identifikátory a <A₁, ..., Aₑ> je seznam argumentů typu. (e je vždy alespoň jedna.)
  • N::I, kde N a I 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átor global, vyhledá se Iglobální obor názvů:
    • Pokud globální obor názvů obsahuje obor názvů s názvem I nula e , 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 a e je nula, qualified_alias_member odkazuje na tento typ.
    • Pokud globální obor názvů obsahuje typ s názvem Ie 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.
  • 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ží N k 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ží NN k oboru názvů, a pak:
      • Pokud obor názvů přidružený N obsahuje název I oboru názvů a e 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 s názvem I a e je nula, qualified_alias_member odkazuje na tento typ.
      • Jinak pokud obor názvů přidružený N obsahuje typ s názvem I s e 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.
  • 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 s global::A a typ System.Net.Sockets.Socket je odkazován s S::Socket. Použití A.x a S.Socket místo toho by způsobilo chyby v době kompilace, protože A by S se vyřešily parametry.

konec příkladu

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á entita global . Pokud by některá entita s názvem global byla v oboru, přeložila globalglobal.A by se na tuto entitu.

Použití global jako identifikátor levé ruky qualified_alias_member vždy způsobí vyhledávání v global oboru názvů, i když existuje alias s názvem global. 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á a MyGlobalTypes.Aglobal::A překládá na třídu A v 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 A má ve druhém těle oboru názvů dva možné významy, protože A třída i alias A using jsou v oboru. Z tohoto důvodu je použití A v kvalifikovaném názvu A.Stream nejednoznačné a způsobuje chybu v době kompilace. Použití A s kvalifikátorem :: však není chybou, protože A se vyhledá pouze jako alias oboru názvů.

konec příkladu