Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
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
Ayang sepenuhnya memenuhi syarat danB. 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.Ayang sepenuhnya memenuhi syarat danN1.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,
XdanY, 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
Xekstern danY, tetapi definisi aktual dari alias berada di luar program. Kelas bernamaN.Bidentik sekarang dapat dirujuk sebagaiX.N.BdanY.N.B, atau, menggunakan kualifikasi alias namespace,X::N.BdanY::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
N3namespace layanan,Aadalah alias untukN1.N2.A, dan dengan demikian kelasN3.Bberasal dari kelasN1.N2.A. Efek yang sama dapat diperoleh dengan membuat aliasRuntukN1.N2dan kemudian mereferensikanR.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
N1namespace layanan,N2adalah alias untuk beberapa namespace yang definisinya berada di luar kode sumber program. KelasN1.Bberasal dari kelasN2.A. Efek yang sama dapat diperoleh dengan membuat aliasAuntukN2.Adan kemudian mereferensikanA: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
R1danR2hanya meluas ke deklarasi anggota di isi namespace tempat mereka berada, sehinggaR1danR2tidak 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 {} // OkMenggunakan alias bernama
Xmenyebabkan kesalahan karena sudah ada alias bernamaXdi unit kompilasi yang sama. Kelas bernamaYtidak bertentangan dengan alias ekstern bernamaYkarena 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, penggunaanBhasil yang tidak memenuhi syarat dalam kesalahan, karenaN3berisi anggota bernamaBdan isi namespace layanan yang juga mendeklarasikan alias dengan namaB; demikian juga untukA.N3.BKelas dapat dirujuk sebagaiN3.Batauglobal::N3.B. AliasAdapat digunakan dalam qualified-alias-member (§14.9), sepertiA::B. AliasBpada dasarnya tidak berguna. Ini tidak dapat digunakan dalam qualified_alias_member karena hanya alias namespace yang dapat digunakan dalam qualified_alias_member danBalias 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.Adalam deklarasi penyebab kesalahan waktu kompilasiBkarenaRmengacu padaN3.R, bukanN1.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, , danR1.N2.Asetara dan semuanya mengacu pada deklarasi kelas yang nama yang sepenuhnya memenuhi syarat adalahR2.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
N3namespace layanan, jenis anggotaN1.N2tersedia secara langsung, dan dengan demikian kelasN3.Bberasal dari kelasN1.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 diN1. Dengan demikian, referensi keN2.Adalam deklarasi menghasilkan kesalahan waktu kompilasiBkarena tidak ada anggota bernamaN2yang 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
N3namespace layanan,Amengacu padaN3.AbukanN1.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
N1danN2berisi anggotaA, dan karenaN3mengimpor keduanya, mereferensikanAadalahN3kesalahan waktu kompilasi. Dalam situasi ini, konflik dapat diselesaikan baik melalui kualifikasi referensi keA, atau dengan memperkenalkan using_alias_directive yang memilih .AContohnya: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 } } }
N1berisi anggotaAjenis , danCberisi bidangAstatis , dan karenaN2mengimpor keduanya, merujukAsebagai 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
N2namespace layanan, anggota statis dan jenisN1.Aberlapis tersedia secara langsung, dan dengan demikian metodeNini dapat mereferensikan anggotaBdanMdariN1.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
Mekstensi yang terkandung dalamN1.A, tetapi hanya sebagai metode ekstensi. Dengan demikian, referensi pertama keMdalam isiB.Nmenghasilkan kesalahan waktu kompilasi karena tidak ada anggota bernamaMyang 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
M2yang terkandung dalamN1.B, tetapi tidak mengimpor metodeMyang terkandung dalamN1.A. Dengan demikian, referensi keMdalam isiC.Nhasil dalam kesalahan waktu kompilasi karena tidak ada anggota bernamaMyang berada dalam cakupan. Pengembang harus menambahkan arahan keduausing staticuntuk menentukan bahwa metode di juga harus diimporN1.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
publicatauinternalmengakses. Defaultnya adalahinternalakses. - Jenis yang dideklarasikan dalam kelas dapat memiliki
publicakses , ,protected internal,protectedprivate protected,internal, atauprivate. Defaultnya adalahprivateakses. - Jenis yang dideklarasikan dalam struktur dapat memiliki
publicakses , ,internalatauprivate. Defaultnya adalahprivateakses.
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 manaNdanImewakili pengidentifikasi, dan<A₁, ..., Aₑ>merupakan daftar argumen jenis. (eselalu setidaknya satu.) -
N::I, di manaNdanImewakili pengidentifikasi. (Dalam hal ini,edianggap nol.)
Dengan menggunakan notasi ini, arti qualified_alias_member ditentukan sebagai berikut:
- Jika
Nadalah pengidentifikasiglobal, maka namespace global dicari untukI:- Jika namespace global berisi namespace bernama
Idanenol, maka qualified_alias_member merujuk ke namespace tersebut. - Jika tidak, jika namespace global berisi jenis non-generik bernama
Idanenol, maka qualified_alias_member mengacu pada jenis tersebut. - Jika tidak, jika namespace global berisi jenis bernama
Iyang memilikieparameter 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 namespace global berisi namespace bernama
- 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
Ndengan 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
Ndengan namespace, atau ketika unit kompilasi tercapai, program berisi global_using_alias_directive yang terkaitNdengan namespace, maka:- Jika namespace yang terkait dengan
Nberisi namespace bernamaIdaneadalah nol, maka qualified_alias_member mengacu pada namespace tersebut. - Jika tidak, jika namespace yang terkait dengan
Nberisi jenis non-generik bernamaIdaneadalah nol, maka qualified_alias_member mengacu pada jenis tersebut. - Jika tidak, jika namespace yang terkait dengan
Nberisi tipe bernamaIyang memiliki parameter tipee, 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 namespace yang terkait dengan
- 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
- 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
Adirujuk denganglobal::Adan jenisnyaSystem.Net.Sockets.Socketdirujuk denganS::Socket. MenggunakanA.xdanS.Socketsebaliknya akan menyebabkan kesalahan waktu kompilasi karenaAdanSakan diselesaikan ke parameter.contoh akhir
Catatan: Pengidentifikasi
globalhanya 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.Amenyebabkan kesalahan waktu kompilasi karena tidak ada entitas bernamaglobaldalam cakupan. Jika beberapa entitas bernama global berada dalam cakupan, makaglobalinglobal.Aakan diselesaikan ke entitas tersebut.Menggunakan
globalsebagai pengidentifikasi sebelah kiri qualified_alias_member selalu menyebabkan pencarian diglobalnamespace, bahkan jika ada menggunakan alias bernamaglobal. 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.Amenyelesaikan keMyGlobalTypes.Adanglobal::Amenyelesaikan ke kelasAdi 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
Amemiliki dua kemungkinan arti dalam isi namespace kedua karena kelasAdan aliasApenggunaan berada dalam cakupan. Untuk alasan ini, penggunaanAdalam namaA.Streamyang memenuhi syarat bersifat ambigu dan menyebabkan kesalahan waktu kompilasi terjadi. Namun, penggunaanAdengan::kualifikasi bukan kesalahan karenaAhanya dicari sebagai alias namespace.contoh akhir
ECMA C# draft specification