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 arahan (§14.6) dan global menggunakan arahan (§14,5) disediakan untuk memfasilitasi penggunaan namespace layanan.

14.2 Unit kompilasi

compilation_unit terdiri dari nol atau lebih extern_alias_directivediikuti dengan nol atau lebih global_using_directivediikuti dengan nol atau lebih using_directivediikuti oleh nol atau satu global_attributes diikuti oleh compilation_unit_body. Compilation_unit_body dapat berupa nol atau lebih statement_listdiikuti dengan nol atau lebih namespace_member_declaration, atau file_scoped_namespace_declaration. compilation_unit mendefinisikan struktur keseluruhan input.

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 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 global_using_directive, using_directive, global_attributes dan compilation_unit_body unit kompilasi tersebut, tetapi tidak berpengaruh pada unit kompilasi lainnya.

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

Global_using_directiveunit kompilasi memengaruhi global_attributes dan namespace_member_declarationdari semua unit kompilasi dalam program.

global_attributes (§23,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_declarationatau file_scoped_namespace_declaration dari setiap unit kompilasi program berkontribusi anggota ke satu ruang deklarasi yang disebut namespace global.

file_scoped_namespace_declaration berkontribusi anggota yang sesuai dengan namespace_declaration yang setara secara semantik (§14,3).

Example:

// 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. file_scoped_namespace_declaration terdiri dari kata kunci namespace, diikuti dengan nama namespace, titik koma, dan daftar opsional extern_alias_directive, using_directivedan type_declaration.

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

File_scoped_namespace_declaration hanya dapat terjadi sebagai deklarasi tingkat atas dalam compilation_unit. Dengan demikian, namespace yang dideklarasikan menjadi anggota namespace global.

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

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

Qualified_identifiernamespace_declaration dan file_scoped_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.

Example:

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

secara semantik setara dengan

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

contoh akhir

file_scoped_namespace_declaration mengizinkan deklarasi namespace untuk ditulis tanpa blok yang { … } menyertainya.

Example:

namespace Name;
using System;
class C
{
}

secara semantik setara dengan

namespace Name
{
    using System;
    class C
    {
    }
}

contoh akhir

File_scoped_namespace_declaration diperlakukan sama dengan namespace_declaration di lokasi yang sama di compilation_unit dengan qualified_identifier yang sama. extern_alias_directive, using_directivedan type_declarationfile_scoped_namespace_declaration bertindak seolah-olah mereka dinyatakan dalam urutan yang sama di dalam namespace_bodynamespace_declaration itu.

Catatan: Seperti yang ditentukan oleh tata bahasa, unit kompilasi tidak boleh berisi file_scoped_namespace_declaration dan namespace_declaration. Ini tidak boleh berisi beberapa file_scoped_namespace_declaration. Ini tidak boleh berisi file_scoped_namespace_declaration dan pernyataantingkat atas apa pun. type_declarationtidak dapat mendahului file_scoped_namespace_declaration. catatan akhir

Unit kompilasi yang berbeda dapat berkontribusi pada namespace yang sama menggunakan atau kedua sintaks namespace_member_declaration atau file_scoped_namespace_declaration .

Namespace terbuka, dan dua deklarasi namespace dengan nama yang sepenuhnya memenuhi syarat yang sama (§7.8.3) 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

file_scoped_namespace_declaration mengizinkan deklarasi namespace untuk ditulis tanpa blok yang { … } menyertainya.

Example:

namespace Name;
using System;
class C
{
}

secara semantik setara dengan

namespace Name
{
    using System;
    class C
    {
    }
}

contoh akhir

File_scoped_namespace_declaration diperlakukan sama dengan namespace_declaration di lokasi yang sama di compilation_unit dengan qualified_identifier yang sama. extern_alias_directive, using_directivedan type_declarationfile_scoped_namespace_declaration bertindak seolah-olah mereka dinyatakan dalam urutan yang sama di dalam namespace_bodynamespace_declaration itu.

Catatan: Seperti yang ditentukan oleh tata bahasa, unit kompilasi tidak boleh berisi file_scoped_namespace_declaration dan namespace_declaration. Ini tidak boleh berisi beberapa file_scoped_namespace_declaration. Ini tidak boleh berisi file_scoped_namespace_declaration dan pernyataantingkat atas apa pun. type_declarationtidak dapat mendahului file_scoped_namespace_declaration. catatan akhir

Unit kompilasi yang berbeda dapat berkontribusi pada namespace yang sama menggunakan atau kedua sintaks namespace_member_declaration atau file_scoped_namespace_declaration .

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 dijelaskan dalam §7.7.1.

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.6.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 Global menggunakan arahan

14.5.1 Umum

Direktif penggunaan global adalah direktif penggunaan (§14,6) di tingkat atas unit kompilasi.

global_using_directive
    : global_using_alias_directive
    | global_using_namespace_directive
    | global_using_static_directive
    ;

Catatan: Cakupan global_using_directive meluas di atas namespace_member_declarationdari semua unit kompilasi dalam program. Cakupan global_using_directive secara khusus tidak menyertakan global_using_directivelainnya. Dengan demikian, rekan global_using_directives atau mereka yang berasal dari unit kompilasi yang berbeda tidak mempengaruhi satu sama lain, dan urutan penulisannya tidak signifikan. Cakupan global_using_directive secara khusus tidak menyertakan using_directiveyang segera terkandung dalam unit kompilasi program apa pun.

Efek menambahkan global_using_directive ke program dapat dianggap sebagai efek menambahkan using_directive serupa yang diselesaikan ke namespace atau jenis target yang sama ke setiap unit kompilasi program. Namun, target global_using_directive diselesaikan dalam konteks unit kompilasi yang berisinya. catatan akhir

14.5.2 Global menggunakan arahan alias

global_using_alias_directive memperkenalkan pengidentifikasi yang berfungsi sebagai alias untuk namespace layanan atau jenis dalam program.

global_using_alias_directive
    : 'global' using_alias_directive
    ;

Dalam deklarasi anggota di unit kompilasi program apa pun yang berisi global_using_alias_directive, pengidentifikasi yang diperkenalkan oleh global_using_alias_directive dapat digunakan untuk mereferensikan namespace atau jenis yang diberikan.

Pengidentifikasiglobal_using_alias_directive harus unik dalam ruang deklarasi unit kompilasi program apa pun yang berisi global_using_alias_directive.

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

Urutan di mana global_using_alias_directiveditulis tidak memiliki signifikansi, dan resolusi namespace_or_type_name yang direferensikan oleh global_using_alias_directive tidak terpengaruh oleh global_using_alias_directive itu sendiri atau oleh global_using_directivelain atau using_directivedalam program. Dengan kata lain, namespace_or_type_nameglobal_using_alias_directive diselesaikan seolah-olah unit kompilasi yang segera berisi tidak memiliki using_directivedan seluruh program yang berisi tidak memiliki global_using_directive. Namun , global_using_alias_directive dapat dipengaruhi oleh extern_alias_directivedi unit kompilasi yang segera berisi.

global_using_alias_directive dapat membuat alias untuk namespace atau jenis apa pun.

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

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

14.5.3 Global menggunakan direktif namespace

global_using_namespace_directive mengimpor jenis yang terkandung dalam namespace ke dalam program, memungkinkan pengidentifikasi setiap jenis digunakan tanpa kualifikasi.

global_using_namespace_directive
    : 'global' using_namespace_directive
    ;

Dalam deklarasi anggota dalam program yang berisi global_using_namespace_directive, jenis yang terkandung dalam namespace yang diberikan dapat direferensikan secara langsung.

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

Tidak seperti global_using_alias_directive, global_using_namespace_directive dapat mengimpor jenis yang pengidentifikasinya sudah ditentukan dalam unit kompilasi program. Akibatnya, dalam unit kompilasi tertentu, nama yang diimpor oleh global_using_namespace_directive apa pun dalam program disembunyikan oleh anggota bernama serupa di unit kompilasi.

Ketika lebih dari satu namespace atau jenis yang diimpor oleh global_using_namespace_directiveatau global_using_static_directivedalam program yang sama berisi jenis dengan nama yang sama, referensi ke nama tersebut sebagai type_name dianggap ambigu.

Selain itu, ketika lebih dari satu namespace atau jenis yang diimpor oleh global_using_namespace_directives atau global_using_static_directivedalam program yang sama berisi jenis atau anggota dengan nama yang sama, referensi ke nama tersebut sebagai simple_name dianggap ambigu.

Namespace_name yang dirujuk oleh global_using_namespace_directive diselesaikan dengan cara yang sama seperti namespace_or_type_name yang dirujuk oleh global_using_alias_directive. Dengan demikian, global_using_namespace_directivedalam program yang sama tidak mempengaruhi satu sama lain dan dapat ditulis dalam urutan apa pun.

14.5.4 Global menggunakan arahan statis

global_using_static_directive mengimpor jenis berlapis dan anggota statis yang terkandung langsung dalam deklarasi jenis ke dalam program yang berisi, memungkinkan pengidentifikasi setiap anggota dan jenis untuk digunakan tanpa kualifikasi.

global_using_static_directive
    : 'global' using_static_directive
    ;

Dalam deklarasi anggota dalam program yang berisi global_using_static_directive, jenis berlapis yang dapat diakses dan anggota statis (kecuali metode ekstensi) yang terkandung langsung dalam deklarasi jenis yang diberikan dapat direferensikan secara langsung.

Global_using_static_directive secara khusus tidak mengimpor metode ekstensi secara langsung sebagai metode statis, tetapi membuatnya tersedia untuk pemanggilan metode ekstensi.

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

Ambiguitas antara beberapa global_using_namespace_directivedan global_using_static_directives dibahas dalam §14.5.3.

14.6 Menggunakan arahan

14.6.1 Umum

Direktif menggunakan memfasilitasi penggunaan namespace layanan dan jenis yang ditentukan di namespace layanan lain. Menggunakan direktif memengaruhi proses resolusi nama namespace_or_type_name(§7,8) dan simple_names (§12.8.4), tetapi tidak seperti deklarasi, using_directivetidak berkontribusi anggota baru ke ruang deklarasi yang mendasar dari unit kompilasi atau namespace tempat mereka digunakan.

using_directive
    : using_alias_directive
    | using_namespace_directive
    | using_static_directive    
    ;

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

using_namespace_directive (§14.6.3) mengimpor jenis anggota namespace layanan.

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

Cakupan using_directive dijelaskan dalam §7.7.1.

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

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.

Example:

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.

Example:

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.9), seperti A::B. Alias B pada dasarnya tidak berguna. Ini tidak dapat digunakan dalam qualified_alias_member karena hanya alias namespace 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 penulisan using_alias_directivetidak 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 isi unit kompilasi atau namespace layanan yang segera berisi, tetapi dapat dipengaruhi oleh extern_alias_directivedi unit kompilasi atau isi namespace layanan yang segera berisi. Dan, jika using_alias_directive segera terkandung dalam unit kompilasi, tidak terpengaruh oleh global_using_directivedalam program. Dengan kata lain, namespace_or_type_nameusing_alias_directive diselesaikan seolah-olah unit kompilasi yang segera berisi atau isi namespace tidak memiliki using_directives dan, jika using_alias_directive segera terkandung dalam unit kompilasi, program tidak memiliki global_using_directivetetapi memiliki set 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 X ekstern menyertakan using_alias_directive.

contoh akhir

using_alias_directive dapat membuat alias untuk namespace atau jenis apa pun, termasuk namespace layanan tempat nama 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 R1.N2.A setara dan semuanya mengacu pada deklarasi kelas yang nama yang sepenuhnya memenuhi syarat adalah R2.AN1.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 badan namespace layanan dan unit kompilasi yang mencakup bagian tersebut yang dipertimbangkan. Ini dapat mengakibatkan pengidentifikasi yang sama memiliki arti yang berbeda di berbagai bagian.

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

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.

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
}

contoh akhir

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

Example:

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.

Example:

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.

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 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, melainkan, 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.6.4 Menggunakan arahan 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.

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

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

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

14.7 Deklarasi anggota namespace

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

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.8 Jenis deklarasi

type_declaration adalah class_declaration (§15,2), struct_declaration (§16,2), interface_declaration (§19,2), enum_declaration (§20,2), atau delegate_declaration (§21,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.3) 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 jenis adalah S.N, 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, antarmuka, 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.9 Anggota alias yang memenuhi syarat

14.9.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.6.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), berlanjut dengan setiap deklarasi namespace lampiran (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, atau ketika unit kompilasi tercapai, program berisi global_using_alias_directive yang terkait N dengan jenis, maka qualified_alias_member tidak terdefinisi dan terjadi kesalahan waktu kompilasi.
    • Jika tidak, jika deklarasi namespace atau unit kompilasi berisi extern_alias_directive atau using_alias_directive yang terkait N dengan namespace, atau ketika unit kompilasi tercapai, program berisi global_using_alias_directive yang terkait N dengan namespace, maka:
      • Jika namespace yang terkait dengan N berisi namespace bernama I dan e adalah nol, maka qualified_alias_member mengacu pada namespace tersebut.
      • Jika tidak, jika namespace yang terkait dengan N berisi jenis non-generik bernama I dan e adalah nol, maka qualified_alias_member mengacu pada jenis tersebut.
      • Jika tidak, jika namespace yang terkait dengan N berisi tipe bernama I yang memiliki parameter tipe e, maka qualified_alias_member mengacu pada tipe yang dibangun dengan argumen tipe 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.9.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