Bagikan melalui


14 Namespace

14.1 Umum

Program C# diatur menggunakan namespace layanan. Namespace digunakan baik sebagai sistem organisasi "internal" untuk suatu program, dan sebagai sistem organisasi "eksternal"—cara menyajikan elemen program yang terekspos ke program lain.

Menggunakan direktif (§14.5) disediakan untuk memfasilitasi penggunaan namespace layanan.

14.2 Unit kompilasi

compilation_unit terdiri dari nol atau lebih extern_alias_directivediikuti oleh nol atau lebih using_directivediikuti dengan nol atau satu global_attributes diikuti oleh nol atau lebih namespace_member_declarations. compilation_unit mendefinisikan struktur input secara keseluruhan.

compilation_unit
    : extern_alias_directive* using_directive* global_attributes?
      namespace_member_declaration*
    ;

Program C# terdiri dari satu atau beberapa unit kompilasi. Ketika program C# dikompilasi, semua unit kompilasi diproses bersama-sama. Dengan demikian, unit kompilasi dapat bergantung satu sama lain, mungkin dengan cara melingkar.

extern_alias_directiveunit kompilasi memengaruhi using_directive, global_attributes dan namespace_member_declarationunit kompilasi tersebut, tetapi tidak berpengaruh pada unit kompilasi lainnya.

Using_directiveunit kompilasi memengaruhi global_attributes dan namespace_member_declarationunit kompilasi tersebut, tetapi tidak berpengaruh pada unit kompilasi lainnya.

global_attributes (§22,3) dari unit kompilasi mengizinkan spesifikasi atribut untuk rakitan dan modul target. Rakitan dan modul bertindak sebagai kontainer fisik untuk jenis. Rakitan dapat terdiri dari beberapa modul yang terpisah secara fisik.

namespace_member_declarationdari setiap unit kompilasi program berkontribusi anggota ke satu ruang deklarasi yang disebut namespace layanan global.

Contoh:

// File A.cs:
class A {}
// File B.cs:
class B {}

Dua unit kompilasi berkontribusi pada namespace layanan global tunggal, dalam hal ini mendeklarasikan dua kelas dengan nama A yang sepenuhnya memenuhi syarat dan B. Karena kedua unit kompilasi berkontribusi pada ruang deklarasi yang sama, itu akan menjadi kesalahan jika masing-masing berisi deklarasi anggota dengan nama yang sama.

contoh akhir

14.3 Deklarasi Namespace

namespace_declaration terdiri dari namespace kata kunci, diikuti dengan nama dan isi namespace, secara opsional diikuti dengan titik koma.

namespace_declaration
    : 'namespace' qualified_identifier namespace_body ';'?
    ;

qualified_identifier
    : identifier ('.' identifier)*
    ;

namespace_body
    : '{' extern_alias_directive* using_directive*
      namespace_member_declaration* '}'
    ;

Namespace_declaration dapat terjadi sebagai deklarasi tingkat atas dalam compilation_unit atau sebagai deklarasi anggota dalam namespace_declaration lain. Ketika namespace_declaration terjadi sebagai deklarasi tingkat atas dalam compilation_unit, namespace menjadi anggota namespace global. Ketika namespace_declaration terjadi dalam namespace_declaration lain, namespace dalam menjadi anggota namespace layanan luar. Dalam kedua kasus, nama namespace harus unik dalam namespace yang berisi.

Namespace secara implisit public dan deklarasi namespace tidak dapat menyertakan pengubah akses apa pun.

Dalam namespace_body, using_directiveopsional mengimpor nama namespace, jenis, dan anggota lain, yang memungkinkan mereka untuk dirujuk secara langsung alih-alih melalui nama yang memenuhi syarat. Namespace_member_declarationopsional berkontribusi anggota ke ruang deklarasi namespace layanan. Perhatikan bahwa semua using_directiveakan muncul sebelum deklarasi anggota.

Qualified_identifier namespace_declaration mungkin merupakan pengidentifikasi tunggal atau urutan pengidentifikasi yang dipisahkan oleh token "".. Formulir terakhir mengizinkan program untuk menentukan namespace berlapis tanpa secara leksikal menyarangkan beberapa deklarasi namespace layanan.

Contoh:

namespace N1.N2
{
    class A {}
    class B {}
}

secara semantik setara dengan

namespace N1
{
    namespace N2
    {
        class A {}
        class B {}
    }
}

contoh akhir

Namespace terbuka, dan dua deklarasi namespace dengan nama yang sepenuhnya memenuhi syarat yang sama (§7.8.2) berkontribusi pada ruang deklarasi yang sama (§7,3).

Contoh: Dalam kode berikut

namespace N1.N2
{
    class A {}
}

namespace N1.N2
{
    class B {}
}

dua deklarasi namespace di atas berkontribusi pada ruang deklarasi yang sama, dalam hal ini mendeklarasikan dua kelas dengan nama N1.N2.A yang sepenuhnya memenuhi syarat dan N1.N2.B. Karena kedua deklarasi berkontribusi pada ruang deklarasi yang sama, itu akan menjadi kesalahan jika masing-masing berisi deklarasi anggota dengan nama yang sama.

contoh akhir

14.4 Arahan alias ekstern

extern_alias_directive memperkenalkan pengidentifikasi yang berfungsi sebagai alias untuk namespace. Spesifikasi namespace layanan alias berada di luar kode sumber program dan berlaku juga untuk namespace layanan berlapis dari namespace alias.

extern_alias_directive
    : 'extern' 'alias' identifier ';'
    ;

Cakupan extern_alias_directive meluas di atas using_directive, global_attributes, dan namespace_member_declarationyang segera berisi compilation_unit atau namespace_body.

Dalam unit kompilasi atau isi namespace yang berisi extern_alias_directive, pengidentifikasi yang diperkenalkan oleh extern_alias_directive dapat digunakan untuk mereferensikan namespace alias. Ini adalah kesalahan waktu kompilasi agar pengidentifikasi menjadi kata global.

Alias yang diperkenalkan oleh extern_alias_directive sangat mirip dengan alias yang diperkenalkan oleh using_alias_directive. Lihat §14.5.2 untuk diskusi yang lebih rinci tentang extern_alias_directivedan using_alias_directive.

alias adalah kata kunci kontekstual (§6.4.4) dan hanya memiliki arti khusus ketika segera mengikuti extern kata kunci dalam extern_alias_directive.

Kesalahan terjadi jika program menyatakan alias ekstern yang tidak disediakan definisi eksternal.

Contoh: Program berikut mendeklarasikan dan menggunakan dua alias ekstern, X dan Y, yang masing-masing mewakili akar hierarki namespace yang berbeda:

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 ini menyatakan keberadaan alias X ekstern dan Y, tetapi definisi aktual dari alias berada di luar program. Kelas bernama N.B identik sekarang dapat dirujuk sebagai X.N.B dan Y.N.B, atau, menggunakan kualifikasi alias namespace, X::N.B dan Y::N.B. contoh akhir

14.5 Menggunakan arahan

14.5.1 Umum

Menggunakan direktif memfasilitasi penggunaan namespace layanan dan jenis yang ditentukan di namespace layanan lain. Menggunakan arahan berdampak pada proses resolusi nama namespace_or_type_name(§7,8) dan simple_name(§12.8.4), tetapi tidak seperti deklarasi, using_directivetidak berkontribusi anggota baru ke ruang deklarasi dasar unit kompilasi atau namespace tempat mereka digunakan.

using_directive
    : using_alias_directive
    | using_namespace_directive
    | using_static_directive    
    ;

using_alias_directive (§14.5.2) memperkenalkan alias untuk namespace atau jenis.

using_namespace_directive (§14.5.3) mengimpor anggota jenis namespace layanan.

Using_static_directive (§14.5.4) mengimpor jenis berlapis dan anggota statis dari jenis.

Cakupan using_directive meluas di atas namespace_member_declarations yang segera berisi unit kompilasi atau isi namespace layanan. Cakupan using_directive secara khusus tidak menyertakan using_directiveserekannya. Dengan demikian, serekan using_directivetidak mempengaruhi satu sama lain, dan urutan penulisannya tidak signifikan. Sebaliknya, cakupan extern_alias_directive mencakup using_directiveyang ditentukan dalam unit kompilasi atau isi namespace yang sama.

14.5.2 Menggunakan arahan alias

using_alias_directive memperkenalkan pengidentifikasi yang berfungsi sebagai alias untuk namespace layanan atau jenis dalam unit kompilasi atau isi namespace layanan yang segera diapit.

using_alias_directive
    : 'using' identifier '=' namespace_or_type_name ';'
    ;

Dalam atribut global dan deklarasi anggota dalam unit kompilasi atau isi namespace layanan yang berisi using_alias_directive, pengidentifikasi yang diperkenalkan oleh using_alias_directive dapat digunakan untuk mereferensikan namespace atau jenis yang diberikan.

Contoh:

namespace N1.N2
{
    class A {}
}
namespace N3
{
    using A = N1.N2.A;

    class B: A {}
}

Di atas, dalam deklarasi anggota di N3 namespace layanan, A adalah alias untuk N1.N2.A, dan dengan demikian kelas N3.B berasal dari kelas N1.N2.A. Efek yang sama dapat diperoleh dengan membuat alias R untuk N1.N2 dan kemudian mereferensikan R.A:

namespace N3
{
    using R = N1.N2;

    class B : R.A {}
}

contoh akhir

Dalam menggunakan direktif, atribut global, dan deklarasi anggota dalam unit kompilasi atau isi namespace yang berisi extern_alias_directive, pengidentifikasi yang diperkenalkan oleh extern_alias_directive dapat digunakan untuk mereferensikan namespace terkait.

Contoh: Misalnya:

namespace N1
{
    extern alias N2;

    class B : N2::A {}
}

Di atas, dalam deklarasi anggota di N1 namespace layanan, N2 adalah alias untuk beberapa namespace yang definisinya berada di luar kode sumber program. Kelas N1.B berasal dari kelas N2.A. Efek yang sama dapat diperoleh dengan membuat alias A untuk N2.A dan kemudian mereferensikan A:

namespace N1
{
    extern alias N2;

    using A = N2::A;

    class B : A {}
}

contoh akhir

extern_alias_directive atau using_alias_directive membuat alias tersedia dalam unit kompilasi atau isi namespace tertentu, tetapi tidak menyumbangkan anggota baru ke ruang deklarasi yang mendasar. Dengan kata lain, arahan alias tidak transitif, melainkan hanya memengaruhi unit kompilasi atau isi namespace tempatnya terjadi.

Contoh: Dalam kode berikut

namespace N3
{
    extern alias R1;

    using R2 = N1.N2;
}

namespace N3
{
    class B : R1::A, R2.I {} // Error, R1 and R2 unknown
}

cakupan arahan alias yang memperkenalkan R1 dan R2 hanya meluas ke deklarasi anggota di isi namespace tempat mereka berada, sehingga R1 dan R2 tidak diketahui dalam deklarasi namespace kedua. Namun, menempatkan arahan alias dalam unit kompilasi yang berisi menyebabkan alias tersedia dalam kedua deklarasi namespace:

extern alias R1;

using R2 = N1.N2;

namespace N3
{
    class B : R1::A, R2.I {}
}

namespace N3
{
    class C : R1::A, R2.I {}
}

contoh akhir

Setiap extern_alias_directive atau using_alias_directive dalam compilation_unit atau namespace_body menyumbangkan nama ke ruang deklarasi alias (§7,3) dari compilation_unit atau namespace_body yang segera diapit. Pengidentifikasi arahan alias harus unik dalam ruang deklarasi alias yang sesuai. Pengidentifikasi alias tidak perlu unik dalam ruang deklarasi global atau ruang deklarasi namespace yang sesuai.

Contoh:

extern alias X;
extern alias Y;

using X = N1.N2; // Error: alias X already exists

class Y {} // Ok

Menggunakan alias bernama X menyebabkan kesalahan karena sudah ada alias bernama X di unit kompilasi yang sama. Kelas bernama Y tidak bertentangan dengan alias ekstern bernama Y karena nama-nama ini ditambahkan ke ruang deklarasi yang berbeda. Yang pertama ditambahkan ke ruang deklarasi global dan yang terakhir ditambahkan ke ruang deklarasi alias untuk unit kompilasi ini.

Ketika nama alias cocok dengan nama anggota namespace layanan, penggunaan salah satunya harus memenuhi syarat dengan tepat:

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
}

Dalam isi namespace kedua untuk N3, penggunaan B hasil yang tidak memenuhi syarat dalam kesalahan, karena N3 berisi anggota bernama B dan isi namespace layanan yang juga mendeklarasikan alias dengan nama B; demikian juga untuk A. N3.B Kelas dapat dirujuk sebagai N3.B atau global::N3.B. Alias A dapat digunakan dalam qualified-alias-member (§14.8), seperti A::B. Alias B pada dasarnya tidak berguna. Ini tidak dapat digunakan dalam qualified_alias_member karena hanya alias namespace layanan yang dapat digunakan dalam qualified_alias_member dan B alias jenis.

contoh akhir

Sama seperti anggota reguler, nama yang diperkenalkan oleh alias_directives disembunyikan oleh anggota bernama serupa dalam cakupan berlapis.

Contoh: Dalam kode berikut

using R = N1.N2;

namespace N3
{
    class R {}
    class B: R.A {} // Error, R has no member A
}

referensi ke R.A dalam deklarasi penyebab kesalahan waktu kompilasi B karena R mengacu pada N3.R, bukan N1.N2.

contoh akhir

Urutan di mana extern_alias_directiveditulis tidak memiliki signifikansi. Demikian juga, urutan di mana using_alias_directiveditulis tidak memiliki signifikansi, tetapi semua using_alias_directives akan datang setelah semua extern_alias_directivedalam unit kompilasi atau isi namespace yang sama. Resolusi namespace_or_type_name yang direferensikan oleh using_alias_directive tidak dipengaruhi oleh using_alias_directive itu sendiri atau oleh using_directivelain dalam unit kompilasi atau isi namespace layanan yang segera berisi, tetapi dapat dipengaruhi oleh extern_alias_directivedalam unit kompilasi atau isi namespace layanan yang segera berisi. Dengan kata lain, namespace_or_type_name using_alias_directive diselesaikan seolah-olah unit kompilasi atau isi namespace layanan yang segera berisi tidak memiliki using_directivetetapi memiliki kumpulan extern_alias_directiveyang benar.

Contoh: Dalam kode berikut

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
}

using_alias_directive terakhir menghasilkan kesalahan waktu kompilasi karena tidak terpengaruh oleh using_alias_directive sebelumnya. using_alias_directive pertama tidak mengakibatkan kesalahan karena cakupan alias ekstern X menyertakan using_alias_directive.

contoh akhir

using_alias_directive dapat membuat alias untuk namespace atau jenis apa pun, termasuk namespace yang muncul dan namespace layanan atau jenis apa pun yang disarangkan dalam namespace tersebut.

Mengakses namespace layanan atau mengetik melalui alias menghasilkan hasil yang sama persis dengan mengakses namespace layanan atau jenis tersebut melalui nama yang dideklarasikan.

Contoh: Diberikan

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

nama N1.N2.A, , dan R2.A setara dan semuanya mengacu pada deklarasi kelas yang nama yang sepenuhnya memenuhi syarat adalah N1.N2.AR1.N2.A.

contoh akhir

Meskipun setiap bagian dari jenis parsial (§15.2.7) dideklarasikan dalam namespace yang sama, bagian biasanya ditulis dalam deklarasi namespace yang berbeda. Dengan demikian, extern_alias_directivedan using_directiveyang berbeda dapat hadir untuk setiap bagian. Saat menafsirkan nama sederhana (§12.8.4) dalam satu bagian, hanya extern_alias_directivedan using_directivedari isi namespace layanan dan unit kompilasi yang mencakup bagian tersebut yang dipertimbangkan. Ini dapat mengakibatkan pengidentifikasi yang sama memiliki arti yang berbeda di berbagai bagian.

Contoh:

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

contoh akhir

Menggunakan alias dapat memberi nama jenis yang dibuat tertutup, tetapi tidak dapat memberi nama deklarasi jenis generik yang tidak terikat tanpa menyediakan argumen jenis.

Contoh:

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
}

contoh akhir

14.5.3 Menggunakan direktif namespace

using_namespace_directive mengimpor jenis yang terkandung dalam namespace ke dalam unit kompilasi atau isi namespace layanan yang segera diapit, memungkinkan pengidentifikasi setiap jenis digunakan tanpa kualifikasi.

using_namespace_directive
    : 'using' namespace_name ';'
    ;

Dalam deklarasi anggota dalam unit kompilasi atau isi namespace yang berisi using_namespace_directive, jenis yang terkandung dalam namespace layanan yang diberikan dapat direferensikan secara langsung.

Contoh:

namespace N1.N2
{
    class A {}
}

namespace N3
{
    using N1.N2;

    class B : A {}
}

Di atas, dalam deklarasi anggota di N3 namespace layanan, jenis anggota N1.N2 tersedia secara langsung, dan dengan demikian kelas N3.B berasal dari kelas N1.N2.A.

contoh akhir

using_namespace_directive mengimpor jenis yang terkandung dalam namespace yang diberikan, tetapi secara khusus tidak mengimpor namespace berlapis.

Contoh: Dalam kode berikut

namespace N1.N2
{
    class A {}
}

namespace N3
{
    using N1;
    class B : N2.A {} // Error, N2 unknown
}

using_namespace_directive mengimpor jenis yang terkandung dalam N1, tetapi bukan namespace yang ditumpuk di N1. Dengan demikian, referensi ke N2.A dalam deklarasi menghasilkan kesalahan waktu kompilasi B karena tidak ada anggota bernama N2 yang berada dalam cakupan.

contoh akhir

Tidak seperti using_alias_directive, using_namespace_directive dapat mengimpor jenis yang pengidentifikasinya sudah ditentukan dalam unit kompilasi atau isi namespace. Akibatnya, nama yang diimpor oleh using_namespace_directive disembunyikan oleh anggota bernama serupa di unit kompilasi atau isi namespace.

Contoh:

namespace N1.N2
{
    class A {}
    class B {}
}

namespace N3
{
    using N1.N2;
    class A {}
}

Di sini, dalam deklarasi anggota di N3 namespace layanan, A mengacu pada N3.A bukan N1.N2.A.

contoh akhir

Karena nama mungkin ambigu ketika lebih dari satu namespace yang diimpor memperkenalkan nama jenis yang sama, using_alias_directive berguna untuk membedakan referensi.

Contoh: Dalam kode berikut

namespace N1
{
    class A {}
}

namespace N2
{
    class A {}
}

namespace N3
{
    using N1;
    using N2;

    class B : A {} // Error, A is ambiguous
}

baik N1 dan N2 berisi anggota A, dan karena N3 mengimpor keduanya, mereferensikan A adalah N3 kesalahan waktu kompilasi. Dalam situasi ini, konflik dapat diselesaikan baik melalui kualifikasi referensi ke A, atau dengan memperkenalkan using_alias_directive yang memilih .A Contohnya:

namespace N3
{
    using N1;
    using N2;
    using A = N1.A;

    class B : A {} // A means N1.A
}

contoh akhir

Selain itu, ketika lebih dari satu namespace atau jenis yang diimpor oleh using_namespace_directives atau using_static_directivedalam unit kompilasi atau isi namespace yang sama berisi jenis atau anggota dengan nama yang sama, referensi ke nama tersebut sebagai simple_name dianggap ambigu.

Contoh:

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 berisi anggota Ajenis , dan C berisi bidang Astatis , dan karena N2 mengimpor keduanya, merujuk A sebagai simple_name ambigu dan kesalahan waktu kompilasi.

contoh akhir

Seperti using_alias_directive, using_namespace_directive tidak menyumbangkan anggota baru apa pun ke ruang deklarasi yang mendasar dari unit kompilasi atau namespace layanan, tetapi, sebaliknya, hanya memengaruhi unit kompilasi atau isi namespace layanan tempatnya muncul.

Namespace_name yang dirujuk oleh using_namespace_directive diselesaikan dengan cara yang sama seperti namespace_or_type_name yang dirujuk oleh using_alias_directive. Dengan demikian, using_namespace_directivedalam unit kompilasi atau isi namespace yang sama tidak mempengaruhi satu sama lain dan dapat ditulis dalam urutan apa pun.

14.5.4 Menggunakan direktif statis

using_static_directive mengimpor jenis berlapis dan anggota statis yang terkandung langsung dalam deklarasi jenis ke dalam unit kompilasi atau isi namespace layanan yang segera diapit, memungkinkan pengidentifikasi setiap anggota dan jenis untuk digunakan tanpa kualifikasi.

using_static_directive
    : 'using' 'static' type_name ';'
    ;

Dalam deklarasi anggota dalam unit kompilasi atau isi namespace yang berisi using_static_directive, jenis berlapis yang dapat diakses dan anggota statis (kecuali metode ekstensi) yang terkandung langsung dalam deklarasi jenis yang diberikan dapat dirujuk secara langsung.

Contoh:

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();
        }
    }
}

Dalam kode sebelumnya, dalam deklarasi anggota di N2 namespace layanan, anggota statis dan jenis N1.A berlapis tersedia secara langsung, dan dengan demikian metode N ini dapat mereferensikan anggota B dan M dari N1.A.

contoh akhir

Using_static_directive secara khusus tidak mengimpor metode ekstensi secara langsung sebagai metode statis, tetapi membuatnya tersedia untuk pemanggilan metode ekstensi (§12.8.9.3).

Contoh:

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 mengimpor metode M ekstensi yang terkandung dalam N1.A, tetapi hanya sebagai metode ekstensi. Dengan demikian, referensi pertama ke M dalam isi B.N menghasilkan kesalahan waktu kompilasi karena tidak ada anggota bernama M yang berada dalam cakupan.

contoh akhir

using_static_directive hanya mengimpor anggota dan jenis yang dideklarasikan langsung dalam jenis tertentu, bukan anggota dan jenis yang dideklarasikan dalam kelas dasar.

Contoh:

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 mengimpor metode M2 yang terkandung dalam N1.B, tetapi tidak mengimpor metode M yang terkandung dalam N1.A. Dengan demikian, referensi ke M dalam isi C.N hasil dalam kesalahan waktu kompilasi karena tidak ada anggota bernama M yang berada dalam cakupan. Pengembang harus menambahkan arahan kedua using static untuk menentukan bahwa metode di juga harus diimpor N1.A .

contoh akhir

Ambiguitas antara beberapa using_namespace_directives dan using_static_directives dibahas dalam §14.5.3.

14.6 Deklarasi anggota namespace

namespace_member_declaration adalah namespace_declaration (§14,3) atau type_declaration (§14,7).

namespace_member_declaration
    : namespace_declaration
    | type_declaration
    ;

Unit kompilasi atau isi namespace dapat berisi namespace_member_declaration, dan deklarasi tersebut menyumbangkan anggota baru ke ruang deklarasi yang mendasar dari unit kompilasi yang berisi atau isi namespace layanan.

14.7 Jenis deklarasi

type_declaration adalah class_declaration (§15,2), struct_declaration (§16,2), interface_declaration (§18,2), enum_declaration (§19,2), atau delegate_declaration (§20,2).

type_declaration
    : class_declaration
    | struct_declaration
    | interface_declaration
    | enum_declaration
    | delegate_declaration
    ;

type_declaration dapat terjadi sebagai deklarasi tingkat atas di unit kompilasi atau sebagai deklarasi anggota dalam namespace, kelas, atau struktur.

Ketika deklarasi jenis untuk jenis T terjadi sebagai deklarasi tingkat atas dalam unit kompilasi, nama yang sepenuhnya memenuhi syarat (§7.8.2) dari deklarasi jenis sama dengan nama deklarasi yang tidak memenuhi syarat (§7.8.2). Ketika deklarasi jenis untuk jenis T terjadi dalam namespace, kelas, atau deklarasi struktur, nama yang sepenuhnya memenuhi syarat (§7.8.3) dari deklarasi S.Njenis , di mana S adalah nama yang sepenuhnya memenuhi syarat dari namespace, kelas, atau deklarasi struktur yang berisi, dan N merupakan nama deklarasi yang tidak memenuhi syarat.

Jenis yang dideklarasikan dalam kelas atau struktur disebut jenis berlapis (§15.3.9).

Pengubah akses yang diizinkan dan akses default untuk deklarasi jenis tergantung pada konteks di mana deklarasi berlangsung (§7.5.2):

  • Jenis yang dideklarasikan dalam unit kompilasi atau namespace layanan dapat memiliki public atau internal mengakses. Defaultnya adalah internal akses.
  • Jenis yang dideklarasikan dalam kelas dapat memiliki publicakses , , protected internal, protectedprivate protected, internal, atau private . Defaultnya adalah private akses.
  • Jenis yang dideklarasikan dalam struktur dapat memiliki publicakses , , internalatau private . Defaultnya adalah private akses.

14.8 Anggota alias yang memenuhi syarat

14.8.1 Umum

Kualifikasi :: alias namespace memungkinkan untuk menjamin bahwa pencarian nama jenis tidak terpengaruh oleh pengenalan jenis dan anggota baru. Kualifikasi alias namespace selalu muncul di antara dua pengidentifikasi yang disebut sebagai pengidentifikasi sebelah kiri dan kanan. Tidak seperti kualifikasi reguler . , pengidentifikasi :: sebelah kiri kualifikasi hanya dicari sebagai extern atau menggunakan alias.

qualified_alias_member menyediakan akses eksplisit ke namespace layanan global dan untuk memusnahkan atau menggunakan alias yang berpotensi disembunyikan oleh entitas lain.

qualified_alias_member
    : identifier '::' identifier type_argument_list?
    ;

qualified_alias_member dapat digunakan sebagai namespace_or_type_name (§7,8) atau sebagai operan kiri dalam member_access (§12.8.7).

qualified_alias_member terdiri dari dua pengidentifikasi, disebut sebagai pengidentifikasi tangan kiri dan kanan, dipisahkan oleh :: token dan secara opsional diikuti oleh type_argument_list. Ketika pengidentifikasi sebelah kiri bersifat global, maka namespace layanan global dicari untuk pengidentifikasi sebelah kanan. Untuk pengidentifikasi sebelah kiri lainnya, pengidentifikasi tersebut dicari sebagai extern atau menggunakan alias (§14,4 dan §14.5.2). Kesalahan waktu kompilasi terjadi jika tidak ada alias atau alias tersebut mereferensikan jenis. Jika alias mereferensikan namespace layanan, maka namespace layanan tersebut dicari untuk pengidentifikasi sebelah kanan.

qualified_alias_member memiliki salah satu dari dua bentuk:

  • N::I<A₁, ..., Aₑ>, di mana N dan I mewakili pengidentifikasi, dan <A₁, ..., Aₑ> merupakan daftar argumen jenis. (e selalu setidaknya satu.)
  • N::I, di mana N dan I mewakili pengidentifikasi. (Dalam hal ini, e dianggap nol.)

Dengan menggunakan notasi ini, arti qualified_alias_member ditentukan sebagai berikut:

  • Jika N adalah pengidentifikasi global, maka namespace global dicari untuk I:
    • Jika namespace global berisi namespace bernama I dan e nol, maka qualified_alias_member merujuk ke namespace tersebut.
    • Jika tidak, jika namespace global berisi jenis non-generik bernama I dan e nol, maka qualified_alias_member mengacu pada jenis tersebut.
    • Jika tidak, jika namespace global berisi jenis bernama I yang memiliki e parameter jenis, maka qualified_alias_member mengacu pada jenis yang dibangun dengan argumen jenis yang diberikan.
    • Jika tidak, qualified_alias_member tidak terdefinisi dan terjadi kesalahan waktu kompilasi.
  • Jika tidak, dimulai dengan deklarasi namespace layanan (§14.3) segera berisi qualified_alias_member (jika ada), melanjutkan dengan setiap deklarasi namespace layanan yang mencakup (jika ada), dan diakhiri dengan unit kompilasi yang berisi qualified_alias_member, langkah-langkah berikut dievaluasi hingga entitas berada:
    • Jika deklarasi namespace atau unit kompilasi berisi using_alias_directive yang mengaitkan N dengan jenis, maka qualified_alias_member tidak terdefinisi dan terjadi kesalahan waktu kompilasi.
    • Jika tidak, jika deklarasi namespace layanan atau unit kompilasi berisi extern_alias_directive atau using_alias_directive yang terkait N dengan namespace, maka:
      • Jika namespace yang terkait dengan N berisi namespace bernama I dan e nol, maka qualified_alias_member merujuk ke namespace tersebut.
      • Jika tidak, jika namespace yang terkait dengan N berisi jenis non-generik bernama I dan e nol, maka qualified_alias_member mengacu pada jenis tersebut.
      • Jika tidak, jika namespace yang terkait dengan N berisi jenis bernama I yang memiliki e parameter jenis, maka qualified_alias_member mengacu pada jenis yang dibangun dengan argumen jenis yang diberikan.
      • Jika tidak, qualified_alias_member tidak terdefinisi dan terjadi kesalahan waktu kompilasi.
  • Jika tidak, qualified_alias_member tidak terdefinisi dan terjadi kesalahan waktu kompilasi.

Contoh: Dalam kode:

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;
    }
}

kelas A dirujuk dengan global::A dan jenisnya System.Net.Sockets.Socket dirujuk dengan S::Socket. Menggunakan A.x dan S.Socket sebaliknya akan menyebabkan kesalahan waktu kompilasi karena A dan S akan diselesaikan ke parameter.

contoh akhir

Catatan: Pengidentifikasi global hanya memiliki arti khusus saat digunakan sebagai pengidentifikasi sebelah kiri qualified_alias_name. Ini bukan kata kunci dan itu sendiri bukan alias; ini adalah kata kunci kontekstual (§6.4.4). Dalam kode:

class A { }

class C
{
    global.A x; // Error: global is not defined
    global::A y; // Valid: References A in the global namespace
}

menggunakan global.A menyebabkan kesalahan waktu kompilasi karena tidak ada entitas bernama global dalam cakupan. Jika beberapa entitas bernama global berada dalam cakupan, maka global in global.A akan diselesaikan ke entitas tersebut.

Menggunakan global sebagai pengidentifikasi sebelah kiri qualified_alias_member selalu menyebabkan pencarian di global namespace, bahkan jika ada menggunakan alias bernama global. Dalam kode:

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 menyelesaikan ke MyGlobalTypes.A dan global::A menyelesaikan ke kelas A di namespace global.

catatan akhir

14.8.2 Keunikan alias

Setiap unit kompilasi dan isi namespace layanan memiliki ruang deklarasi terpisah untuk alias ekstern dan menggunakan alias. Dengan demikian, sementara nama alias ekstern atau menggunakan alias harus unik dalam set alias ekstern dan menggunakan alias yang dinyatakan dalam unit kompilasi segera atau isi namespace layanan, alias diizinkan untuk memiliki nama yang sama dengan jenis atau namespace selama hanya digunakan dengan :: kualifikasi.

Contoh: Dalam hal berikut:

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

nama A memiliki dua kemungkinan arti dalam isi namespace kedua karena kelas A dan alias A penggunaan berada dalam cakupan. Untuk alasan ini, penggunaan A dalam nama A.Stream yang memenuhi syarat bersifat ambigu dan menyebabkan kesalahan waktu kompilasi terjadi. Namun, penggunaan A dengan :: kualifikasi bukan kesalahan karena A hanya dicari sebagai alias namespace.

contoh akhir