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 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 keseluruhan input.
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 (§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_declarationdari setiap unit kompilasi program berkontribusi anggota ke satu ruang deklarasi yang disebut namespace layanan global.
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.
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, 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_identifiernamespace_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
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
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 yanglebih rinci tentang extern_alias_directive dan 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 Menggunakan arahan
14.5.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.5.2) memperkenalkan alias untuk namespace atau jenis.
using_namespace_directive (§14.5.3) mengimpor jenis anggota 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 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.8), 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. Dengan kata lain, namespace_or_type_nameusing_alias_directive diselesaikan seolah-olah unit kompilasi atau isi namespace layanan yang segera berisi tidak memiliki 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.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 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.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.
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.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 (§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.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 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, maka qualified_alias_member tidak ditentukan dan terjadi kesalahan waktu kompilasi.
- Jika tidak, jika deklarasi namespace layanan atau unit kompilasi berisi extern_alias_directive atau using_alias_directive yang terkait
Ndengan 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 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.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
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