Sdílet prostřednictvím


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_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 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.

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.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

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ů 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 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ů 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 v kvalifikovaném členu aliasu (§14.8), 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ů. 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.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.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 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.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 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.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 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.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ₑ>, 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, 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á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.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ž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