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 input secara keseluruhan.
compilation_unit
: extern_alias_directive* using_directive* global_attributes?
namespace_member_declaration*
;
Program C# terdiri dari satu atau beberapa unit kompilasi. Ketika program C# dikompilasi, semua unit kompilasi diproses bersama-sama. Dengan demikian, unit kompilasi dapat bergantung satu sama lain, mungkin dengan cara melingkar.
extern_alias_directiveunit kompilasi memengaruhi using_directive, global_attributes dan namespace_member_declarationunit kompilasi tersebut, tetapi tidak berpengaruh pada unit kompilasi lainnya.
Using_directiveunit kompilasi memengaruhi global_attributes dan namespace_member_declarationunit kompilasi tersebut, tetapi tidak berpengaruh pada unit kompilasi lainnya.
global_attributes (§22,3) dari unit kompilasi mengizinkan spesifikasi atribut untuk rakitan dan modul target. Rakitan dan modul bertindak sebagai kontainer fisik untuk jenis. Rakitan dapat terdiri dari beberapa modul yang terpisah secara fisik.
namespace_member_declarationdari setiap unit kompilasi program berkontribusi anggota ke satu ruang deklarasi yang disebut namespace layanan global.
Contoh:
// File A.cs: class A {} // File B.cs: class B {}
Dua unit kompilasi berkontribusi pada namespace layanan global tunggal, dalam hal ini mendeklarasikan dua kelas dengan nama
A
yang sepenuhnya memenuhi syarat 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, yang memungkinkan mereka untuk dirujuk secara langsung alih-alih melalui nama yang memenuhi syarat. Namespace_member_declarationopsional berkontribusi anggota ke ruang deklarasi namespace layanan. Perhatikan bahwa semua using_directiveakan muncul sebelum deklarasi anggota.
Qualified_identifier namespace_declaration mungkin merupakan pengidentifikasi tunggal atau urutan pengidentifikasi yang dipisahkan oleh token "".
. Formulir terakhir mengizinkan program untuk menentukan namespace berlapis tanpa secara leksikal menyarangkan beberapa deklarasi namespace layanan.
Contoh:
namespace N1.N2 { class A {} class B {} }
secara semantik setara dengan
namespace N1 { namespace N2 { class A {} class B {} } }
contoh akhir
Namespace terbuka, dan dua deklarasi namespace dengan nama yang sepenuhnya memenuhi syarat yang sama (§7.8.2) berkontribusi pada ruang deklarasi yang sama (§7,3).
Contoh: Dalam kode berikut
namespace N1.N2 { class A {} } namespace N1.N2 { class B {} }
dua deklarasi namespace di atas berkontribusi pada ruang deklarasi yang sama, dalam hal ini mendeklarasikan dua kelas dengan nama
N1.N2.A
yang sepenuhnya memenuhi syarat 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 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
danY
, 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 danY
, tetapi definisi aktual dari alias berada di luar program. Kelas bernamaN.B
identik sekarang dapat dirujuk sebagaiX.N.B
danY.N.B
, atau, menggunakan kualifikasi alias namespace,X::N.B
danY::N.B
. contoh akhir
14.5 Menggunakan arahan
14.5.1 Umum
Menggunakan direktif memfasilitasi penggunaan namespace layanan dan jenis yang ditentukan di namespace layanan lain. Menggunakan arahan berdampak pada proses resolusi nama namespace_or_type_name(§7,8) dan simple_name(§12.8.4), tetapi tidak seperti deklarasi, using_directivetidak berkontribusi anggota baru ke ruang deklarasi dasar unit kompilasi atau namespace tempat mereka digunakan.
using_directive
: using_alias_directive
| using_namespace_directive
| using_static_directive
;
using_alias_directive (§14.5.2) memperkenalkan alias untuk namespace atau jenis.
using_namespace_directive (§14.5.3) mengimpor anggota jenis namespace layanan.
Using_static_directive (§14.5.4) mengimpor jenis berlapis dan anggota statis dari jenis.
Cakupan using_directive meluas di atas namespace_member_declarations yang segera berisi unit kompilasi atau isi namespace layanan. Cakupan using_directive secara khusus tidak menyertakan using_directiveserekannya. Dengan demikian, serekan using_directivetidak mempengaruhi satu sama lain, dan urutan penulisannya tidak signifikan. Sebaliknya, cakupan extern_alias_directive mencakup using_directiveyang ditentukan dalam unit kompilasi atau isi namespace yang sama.
14.5.2 Menggunakan arahan alias
using_alias_directive memperkenalkan pengidentifikasi yang berfungsi sebagai alias untuk namespace layanan atau jenis dalam unit kompilasi atau isi namespace layanan yang segera diapit.
using_alias_directive
: 'using' identifier '=' namespace_or_type_name ';'
;
Dalam atribut global dan deklarasi anggota dalam unit kompilasi atau isi namespace layanan yang berisi using_alias_directive, pengidentifikasi yang diperkenalkan oleh using_alias_directive dapat digunakan untuk mereferensikan namespace atau jenis yang diberikan.
Contoh:
namespace N1.N2 { class A {} } namespace N3 { using A = N1.N2.A; class B: A {} }
Di atas, dalam deklarasi anggota di
N3
namespace layanan,A
adalah alias untukN1.N2.A
, dan dengan demikian kelasN3.B
berasal dari kelasN1.N2.A
. Efek yang sama dapat diperoleh dengan membuat aliasR
untukN1.N2
dan 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
N1
namespace layanan,N2
adalah alias untuk beberapa namespace yang definisinya berada di luar kode sumber program. KelasN1.B
berasal dari kelasN2.A
. Efek yang sama dapat diperoleh dengan membuat aliasA
untukN2.A
dan 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
R1
danR2
hanya meluas ke deklarasi anggota di isi namespace tempat mereka berada, sehinggaR1
danR2
tidak diketahui dalam deklarasi namespace kedua. Namun, menempatkan arahan alias dalam unit kompilasi yang berisi menyebabkan alias tersedia dalam kedua deklarasi namespace:extern alias R1; using R2 = N1.N2; namespace N3 { class B : R1::A, R2.I {} } namespace N3 { class C : R1::A, R2.I {} }
contoh akhir
Setiap extern_alias_directive atau using_alias_directive dalam compilation_unit atau namespace_body menyumbangkan nama ke ruang deklarasi alias (§7,3) dari compilation_unit atau namespace_body yang segera diapit. Pengidentifikasi arahan alias harus unik dalam ruang deklarasi alias yang sesuai. Pengidentifikasi alias tidak perlu unik dalam ruang deklarasi global atau ruang deklarasi namespace yang sesuai.
Contoh:
extern alias X; extern alias Y; using X = N1.N2; // Error: alias X already exists class Y {} // Ok
Menggunakan alias bernama
X
menyebabkan kesalahan karena sudah ada alias bernamaX
di unit kompilasi yang sama. Kelas bernamaY
tidak bertentangan dengan alias ekstern bernamaY
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
, penggunaanB
hasil yang tidak memenuhi syarat dalam kesalahan, karenaN3
berisi anggota bernamaB
dan isi namespace layanan yang juga mendeklarasikan alias dengan namaB
; demikian juga untukA
.N3.B
Kelas dapat dirujuk sebagaiN3.B
atauglobal::N3.B
. AliasA
dapat digunakan dalam qualified-alias-member (§14.8), sepertiA::B
. AliasB
pada dasarnya tidak berguna. Ini tidak dapat digunakan dalam qualified_alias_member karena hanya alias namespace layanan yang dapat digunakan dalam qualified_alias_member danB
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 kompilasiB
karenaR
mengacu padaN3.R
, bukanN1.N2
.contoh akhir
Urutan di mana extern_alias_directiveditulis tidak memiliki signifikansi. Demikian juga, urutan di mana using_alias_directiveditulis tidak memiliki signifikansi, tetapi semua using_alias_directives akan datang setelah semua extern_alias_directivedalam unit kompilasi atau isi namespace yang sama. Resolusi namespace_or_type_name yang direferensikan oleh using_alias_directive tidak dipengaruhi oleh using_alias_directive itu sendiri atau oleh using_directivelain dalam unit kompilasi atau isi namespace layanan yang segera berisi, tetapi dapat dipengaruhi oleh extern_alias_directivedalam unit kompilasi atau isi namespace layanan yang segera berisi. Dengan kata lain, namespace_or_type_name using_alias_directive diselesaikan seolah-olah unit kompilasi atau isi namespace layanan yang segera berisi tidak memiliki using_directivetetapi memiliki kumpulan extern_alias_directiveyang benar.
Contoh: Dalam kode berikut
namespace N1.N2 {} namespace N3 { extern alias X; using R1 = X::N; // OK using R2 = N1; // OK using R3 = N1.N2; // OK using R4 = R2.N2; // Error, R2 unknown }
using_alias_directive terakhir menghasilkan kesalahan waktu kompilasi karena tidak terpengaruh oleh using_alias_directive sebelumnya. using_alias_directive pertama tidak mengakibatkan kesalahan karena cakupan alias ekstern X menyertakan using_alias_directive.
contoh akhir
using_alias_directive dapat membuat alias untuk namespace atau jenis apa pun, termasuk namespace yang muncul dan namespace layanan atau jenis apa pun yang disarangkan dalam namespace tersebut.
Mengakses namespace layanan atau mengetik melalui alias menghasilkan hasil yang sama persis dengan mengakses namespace layanan atau jenis tersebut melalui nama yang dideklarasikan.
Contoh: Diberikan
namespace N1.N2 { class A {} } namespace N3 { using R1 = N1; using R2 = N1.N2; class B { N1.N2.A a; // refers to N1.N2.A R1.N2.A b; // refers to N1.N2.A R2.A c; // refers to N1.N2.A } }
nama
N1.N2.A
, , danR2.A
setara dan semuanya mengacu pada deklarasi kelas yang nama yang sepenuhnya memenuhi syarat adalahN1.N2.A
R1.N2.A
.contoh akhir
Meskipun setiap bagian dari jenis parsial (§15.2.7) dideklarasikan dalam namespace yang sama, bagian biasanya ditulis dalam deklarasi namespace yang berbeda. Dengan demikian, extern_alias_directivedan using_directiveyang berbeda dapat hadir untuk setiap bagian. Saat menafsirkan nama sederhana (§12.8.4) dalam satu bagian, hanya extern_alias_directivedan using_directivedari isi namespace layanan dan unit kompilasi yang mencakup bagian tersebut yang dipertimbangkan. Ini dapat mengakibatkan pengidentifikasi yang sama memiliki arti yang berbeda di berbagai bagian.
Contoh:
namespace N { using List = System.Collections.ArrayList; partial class A { List x; // x has type System.Collections.ArrayList } } namespace N { using List = Widgets.LinkedList; partial class A { List y; // y has type Widgets.LinkedList } }
contoh akhir
Menggunakan alias dapat memberi nama jenis yang dibuat tertutup, tetapi tidak dapat memberi nama deklarasi jenis generik yang tidak terikat tanpa menyediakan argumen jenis.
Contoh:
namespace N1 { class A<T> { class B {} } } namespace N2 { using W = N1.A; // Error, cannot name unbound generic type using X = N1.A.B; // Error, cannot name unbound generic type using Y = N1.A<int>; // Ok, can name closed constructed type using Z<T> = N1.A<T>; // Error, using alias cannot have type parameters }
contoh akhir
14.5.3 Menggunakan direktif namespace
using_namespace_directive mengimpor jenis yang terkandung dalam namespace ke dalam unit kompilasi atau isi namespace layanan yang segera diapit, memungkinkan pengidentifikasi setiap jenis digunakan tanpa kualifikasi.
using_namespace_directive
: 'using' namespace_name ';'
;
Dalam deklarasi anggota dalam unit kompilasi atau isi namespace yang berisi using_namespace_directive, jenis yang terkandung dalam namespace layanan yang diberikan dapat direferensikan secara langsung.
Contoh:
namespace N1.N2 { class A {} } namespace N3 { using N1.N2; class B : A {} }
Di atas, dalam deklarasi anggota di
N3
namespace layanan, jenis anggotaN1.N2
tersedia secara langsung, dan dengan demikian kelasN3.B
berasal 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.A
dalam deklarasi menghasilkan kesalahan waktu kompilasiB
karena tidak ada anggota bernamaN2
yang berada dalam cakupan.contoh akhir
Tidak seperti using_alias_directive, using_namespace_directive dapat mengimpor jenis yang pengidentifikasinya sudah ditentukan dalam unit kompilasi atau isi namespace. Akibatnya, nama yang diimpor oleh using_namespace_directive disembunyikan oleh anggota bernama serupa di unit kompilasi atau isi namespace.
Contoh:
namespace N1.N2 { class A {} class B {} } namespace N3 { using N1.N2; class A {} }
Di sini, dalam deklarasi anggota di
N3
namespace layanan,A
mengacu padaN3.A
bukanN1.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
danN2
berisi anggotaA
, dan karenaN3
mengimpor keduanya, mereferensikanA
adalahN3
kesalahan waktu kompilasi. Dalam situasi ini, konflik dapat diselesaikan baik melalui kualifikasi referensi keA
, atau dengan memperkenalkan using_alias_directive yang memilih .A
Contohnya:namespace N3 { using N1; using N2; using A = N1.A; class B : A {} // A means N1.A }
contoh akhir
Selain itu, ketika lebih dari satu namespace atau jenis yang diimpor oleh using_namespace_directives atau using_static_directivedalam unit kompilasi atau isi namespace yang sama berisi jenis atau anggota dengan nama yang sama, referensi ke nama tersebut sebagai simple_name dianggap ambigu.
Contoh:
namespace N1 { class A {} } class C { public static int A; } namespace N2 { using N1; using static C; class B { void M() { A a = new A(); // Ok, A is unambiguous as a type-name A.Equals(2); // Error, A is ambiguous as a simple-name } } }
N1
berisi anggotaA
jenis , danC
berisi bidangA
statis , dan karenaN2
mengimpor keduanya, merujukA
sebagai simple_name ambigu dan kesalahan waktu kompilasi.contoh akhir
Seperti using_alias_directive, using_namespace_directive tidak menyumbangkan anggota baru apa pun ke ruang deklarasi yang mendasar dari unit kompilasi atau namespace layanan, tetapi, sebaliknya, hanya memengaruhi unit kompilasi atau isi namespace layanan tempatnya muncul.
Namespace_name yang dirujuk oleh using_namespace_directive diselesaikan dengan cara yang sama seperti namespace_or_type_name yang dirujuk oleh using_alias_directive. Dengan demikian, using_namespace_directivedalam unit kompilasi atau isi namespace yang sama tidak mempengaruhi satu sama lain dan dapat ditulis dalam urutan apa pun.
14.5.4 Menggunakan direktif statis
using_static_directive mengimpor jenis berlapis dan anggota statis yang terkandung langsung dalam deklarasi jenis ke dalam unit kompilasi atau isi namespace layanan yang segera diapit, memungkinkan pengidentifikasi setiap anggota dan jenis untuk digunakan tanpa kualifikasi.
using_static_directive
: 'using' 'static' type_name ';'
;
Dalam deklarasi anggota dalam unit kompilasi atau isi namespace yang berisi using_static_directive, jenis berlapis yang dapat diakses dan anggota statis (kecuali metode ekstensi) yang terkandung langsung dalam deklarasi jenis yang diberikan dapat dirujuk secara langsung.
Contoh:
namespace N1 { class A { public class B {} public static B M() => new B(); } } namespace N2 { using static N1.A; class C { void N() { B b = M(); } } }
Dalam kode sebelumnya, dalam deklarasi anggota di
N2
namespace layanan, anggota statis dan jenisN1.A
berlapis tersedia secara langsung, dan dengan demikian metodeN
ini dapat mereferensikan anggotaB
danM
dariN1.A
.contoh akhir
Using_static_directive secara khusus tidak mengimpor metode ekstensi secara langsung sebagai metode statis, tetapi membuatnya tersedia untuk pemanggilan metode ekstensi (§12.8.9.3).
Contoh:
namespace N1 { static class A { public static void M(this string s){} } } namespace N2 { using static N1.A; class B { void N() { M("A"); // Error, M unknown "B".M(); // Ok, M known as extension method N1.A.M("C"); // Ok, fully qualified } } }
using_static_directive mengimpor metode
M
ekstensi yang terkandung dalamN1.A
, tetapi hanya sebagai metode ekstensi. Dengan demikian, referensi pertama keM
dalam isiB.N
menghasilkan kesalahan waktu kompilasi karena tidak ada anggota bernamaM
yang berada dalam cakupan.contoh akhir
using_static_directive hanya mengimpor anggota dan jenis yang dideklarasikan langsung dalam jenis tertentu, bukan anggota dan jenis yang dideklarasikan dalam kelas dasar.
Contoh:
namespace N1 { class A { public static void M(string s){} } class B : A { public static void M2(string s){} } } namespace N2 { using static N1.B; class C { void N() { M2("B"); // OK, calls B.M2 M("C"); // Error. M unknown } } }
using_static_directive mengimpor metode
M2
yang terkandung dalamN1.B
, tetapi tidak mengimpor metodeM
yang terkandung dalamN1.A
. Dengan demikian, referensi keM
dalam isiC.N
hasil dalam kesalahan waktu kompilasi karena tidak ada anggota bernamaM
yang berada dalam cakupan. Pengembang harus menambahkan arahan keduausing static
untuk 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 (§18,2), enum_declaration (§19,2), atau delegate_declaration (§20,2).
type_declaration
: class_declaration
| struct_declaration
| interface_declaration
| enum_declaration
| delegate_declaration
;
type_declaration dapat terjadi sebagai deklarasi tingkat atas di unit kompilasi atau sebagai deklarasi anggota dalam namespace, kelas, atau struktur.
Ketika deklarasi jenis untuk jenis T
terjadi sebagai deklarasi tingkat atas dalam unit kompilasi, nama yang sepenuhnya memenuhi syarat (§7.8.2) dari deklarasi jenis sama dengan nama deklarasi yang tidak memenuhi syarat (§7.8.2). Ketika deklarasi jenis untuk jenis T
terjadi dalam namespace, kelas, atau deklarasi struktur, nama yang sepenuhnya memenuhi syarat (§7.8.3) dari deklarasi S.N
jenis , di mana S
adalah nama yang sepenuhnya memenuhi syarat dari namespace, kelas, atau deklarasi struktur yang berisi, dan N
merupakan nama deklarasi yang tidak memenuhi syarat.
Jenis yang dideklarasikan dalam kelas atau struktur disebut jenis berlapis (§15.3.9).
Pengubah akses yang diizinkan dan akses default untuk deklarasi jenis tergantung pada konteks di mana deklarasi berlangsung (§7.5.2):
- Jenis yang dideklarasikan dalam unit kompilasi atau namespace layanan dapat memiliki
public
atauinternal
mengakses. Defaultnya adalahinternal
akses. - Jenis yang dideklarasikan dalam kelas dapat memiliki
public
akses , ,protected internal
,protected
private protected
,internal
, atauprivate
. Defaultnya adalahprivate
akses. - Jenis yang dideklarasikan dalam struktur dapat memiliki
public
akses , ,internal
atauprivate
. Defaultnya adalahprivate
akses.
14.8 Anggota alias yang memenuhi syarat
14.8.1 Umum
Kualifikasi ::
alias namespace memungkinkan untuk menjamin bahwa pencarian nama jenis tidak terpengaruh oleh pengenalan jenis dan anggota baru. Kualifikasi alias namespace selalu muncul di antara dua pengidentifikasi yang disebut sebagai pengidentifikasi sebelah kiri dan kanan. Tidak seperti kualifikasi reguler .
, pengidentifikasi ::
sebelah kiri kualifikasi hanya dicari sebagai extern atau menggunakan alias.
qualified_alias_member menyediakan akses eksplisit ke namespace layanan global dan untuk memusnahkan atau menggunakan alias yang berpotensi disembunyikan oleh entitas lain.
qualified_alias_member
: identifier '::' identifier type_argument_list?
;
qualified_alias_member dapat digunakan sebagai namespace_or_type_name (§7,8) atau sebagai operan kiri dalam member_access (§12.8.7).
qualified_alias_member terdiri dari dua pengidentifikasi, disebut sebagai pengidentifikasi tangan kiri dan kanan, dipisahkan oleh ::
token dan secara opsional diikuti oleh type_argument_list. Ketika pengidentifikasi sebelah kiri bersifat global, maka namespace layanan global dicari untuk pengidentifikasi sebelah kanan. Untuk pengidentifikasi sebelah kiri lainnya, pengidentifikasi tersebut dicari sebagai extern atau menggunakan alias (§14,4 dan §14.5.2). Kesalahan waktu kompilasi terjadi jika tidak ada alias atau alias tersebut mereferensikan jenis. Jika alias mereferensikan namespace layanan, maka namespace layanan tersebut dicari untuk pengidentifikasi sebelah kanan.
qualified_alias_member memiliki salah satu dari dua bentuk:
N::I<A₁, ..., Aₑ>
, di manaN
danI
mewakili pengidentifikasi, dan<A₁, ..., Aₑ>
merupakan daftar argumen jenis. (e
selalu setidaknya satu.)N::I
, di manaN
danI
mewakili pengidentifikasi. (Dalam hal ini,e
dianggap nol.)
Dengan menggunakan notasi ini, arti qualified_alias_member ditentukan sebagai berikut:
- Jika
N
adalah pengidentifikasiglobal
, maka namespace global dicari untukI
:- Jika namespace global berisi namespace bernama
I
dane
nol, maka qualified_alias_member merujuk ke namespace tersebut. - Jika tidak, jika namespace global berisi jenis non-generik bernama
I
dane
nol, maka qualified_alias_member mengacu pada jenis tersebut. - Jika tidak, jika namespace global berisi jenis bernama
I
yang memilikie
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 namespace global berisi namespace bernama
- Jika tidak, dimulai dengan deklarasi namespace layanan (§14.3) segera berisi qualified_alias_member (jika ada), melanjutkan dengan setiap deklarasi namespace layanan yang mencakup (jika ada), dan diakhiri dengan unit kompilasi yang berisi qualified_alias_member, langkah-langkah berikut dievaluasi hingga entitas berada:
- Jika deklarasi namespace atau unit kompilasi berisi using_alias_directive yang mengaitkan N dengan jenis, maka qualified_alias_member tidak terdefinisi dan terjadi kesalahan waktu kompilasi.
- Jika tidak, jika deklarasi namespace layanan atau unit kompilasi berisi extern_alias_directive atau using_alias_directive yang terkait
N
dengan namespace, maka:- Jika namespace yang terkait dengan
N
berisi namespace bernamaI
dane
nol, maka qualified_alias_member merujuk ke namespace tersebut. - Jika tidak, jika namespace yang terkait dengan
N
berisi jenis non-generik bernamaI
dane
nol, maka qualified_alias_member mengacu pada jenis tersebut. - Jika tidak, jika namespace yang terkait dengan
N
berisi jenis bernamaI
yang memilikie
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 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
A
dirujuk denganglobal::A
dan jenisnyaSystem.Net.Sockets.Socket
dirujuk denganS::Socket
. MenggunakanA.x
danS.Socket
sebaliknya akan menyebabkan kesalahan waktu kompilasi karenaA
danS
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 bernamaglobal
dalam cakupan. Jika beberapa entitas bernama global berada dalam cakupan, makaglobal
inglobal.A
akan diselesaikan ke entitas tersebut.Menggunakan
global
sebagai pengidentifikasi sebelah kiri qualified_alias_member selalu menyebabkan pencarian diglobal
namespace, 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.A
menyelesaikan keMyGlobalTypes.A
danglobal::A
menyelesaikan ke kelasA
di namespace global.catatan akhir
14.8.2 Keunikan alias
Setiap unit kompilasi dan isi namespace layanan memiliki ruang deklarasi terpisah untuk alias ekstern dan menggunakan alias. Dengan demikian, sementara nama alias ekstern atau menggunakan alias harus unik dalam set alias ekstern dan menggunakan alias yang dinyatakan dalam unit kompilasi segera atau isi namespace layanan, alias diizinkan untuk memiliki nama yang sama dengan jenis atau namespace selama hanya digunakan dengan ::
kualifikasi.
Contoh: Dalam hal berikut:
namespace N { public class A {} public class B {} } namespace N { using A = System.IO; class X { A.Stream s1; // Error, A is ambiguous A::Stream s2; // Ok } }
nama
A
memiliki dua kemungkinan arti dalam isi namespace kedua karena kelasA
dan aliasA
penggunaan berada dalam cakupan. Untuk alasan ini, penggunaanA
dalam namaA.Stream
yang memenuhi syarat bersifat ambigu dan menyebabkan kesalahan waktu kompilasi terjadi. Namun, penggunaanA
dengan::
kualifikasi bukan kesalahan karenaA
hanya dicari sebagai alias namespace.contoh akhir
ECMA C# draft specification