Bagikan melalui


Direktif Penggunaan Global

Nota

Artikel ini adalah spesifikasi fitur. Spesifikasi berfungsi sebagai dokumen desain untuk fitur tersebut. Ini termasuk perubahan spesifikasi yang diusulkan, bersama dengan informasi yang diperlukan selama desain dan pengembangan fitur. Artikel ini diterbitkan sampai perubahan spesifikasi yang diusulkan diselesaikan dan dimasukkan dalam spesifikasi ECMA saat ini.

Mungkin ada beberapa perbedaan antara spesifikasi fitur dan implementasi yang selesai. Perbedaan tersebut dicatat dalam catatan terkait rapat desain bahasa (LDM) .

Anda dapat mempelajari lebih lanjut tentang proses untuk mengadopsi speklet fitur ke dalam standar bahasa C# dalam artikel tentang spesifikasi .

Edisi Unggulan: https://github.com/dotnet/csharplang/issues/3428

Sintaks untuk direktif penggunaan diperluas dengan kata kunci global opsional yang dapat mendahului kata kunci using:

compilation_unit
    : extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

global_using_directive
    : global_using_alias_directive
    | global_using_namespace_directive
    | global_using_static_directive
    ;

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;
    
global_using_static_directive
    : 'global' 'using' 'static' type_name ';'
    ;
  • global_using_directivediperbolehkan hanya pada tingkat Unit Kompilasi (tidak dapat digunakan di dalam namespace_declaration).
  • global_using_directive, jika ada, harus mendahului semua using_directive.
  • Cakupan global_using_directivemencakup namespace_member_declarationdari semua unit kompilasi dalam program. Cakupan global_using_directive secara khusus tidak menyertakan global_using_directivelainnya. Dengan demikian, rekan global_using_directiveatau mereka yang berasal dari unit kompilasi yang berbeda tidak mempengaruhi satu sama lain, dan urutan penulisannya tidak signifikan. Cakupan global_using_directive tidak secara spesifik termasuk using_directiveyang berada langsung dalam satuan kompilasi dalam program.

Efek menambahkan global_using_directive ke program dapat dianggap mirip dengan efek menambahkan using_directive serupa yang merujuk ke namespace atau jenis target yang sama untuk setiap unit kompilasi dari program tersebut. Namun, target global_using_directive diselesaikan dalam konteks unit kompilasi yang berisinya.

Cakupan §7,7

Ini adalah poin-poin yang relevan dengan tambahan yang diusulkan (yang di menjaditebal):

  • Cakupan nama yang ditentukan oleh extern_alias_directive mencakup global_using_directive,using_directive, global_attributes, dan namespace_member_declarationdari unit kompilasi atau badan namespace yang segera mengandungnya. extern_alias_directive tidak menambahkan anggota baru ke ruang deklarasi dasar. Dengan kata lain, extern_alias_directive tidak transitif, melainkan hanya memengaruhi unit kompilasi atau isi namespace tempatnya terjadi.
  • Cakupan nama yang ditentukan atau diimpor oleh global_using_directive meluas ke global_attributes dan namespace_member_declarationdari semua compilation_unitdalam program.

§7,8 Namespace dan nama tipe

Perubahan dilakukan pada algoritma yang menentukan arti namespace_or_type_name sebagai berikut.

Ini adalah poin yang relevan dengan penambahan yang diusulkan (yang ditebalkan):

  • Jika namespace_or_type_name adalah dalam bentuk I atau dalam bentuk I<A1, ..., Ak>:
    • Jika K nol dan namespace_or_type_name muncul dalam deklarasi metode generik (§15,6) dan jika deklarasi tersebut menyertakan parameter jenis (§15,2,3) dengan nama I, maka namespace_or_type_name mengacu pada parameter jenis tersebut.
    • Jika tidak, jika namespace_or_type_name muncul dalam deklarasi jenis, maka untuk setiap jenis instans T (§15.3.2), dimulai dengan jenis instans dari deklarasi jenis tersebut dan melanjutkan dengan jenis instans dari setiap kelas penutup atau deklarasi struktur (jika ada):
      • Jika K nol dan deklarasi T menyertakan parameter jenis dengan nama I, maka namespace_or_type_name mengacu pada parameter jenis tersebut.
      • Jika tidak, jika namespace_or_type_name muncul dalam isi deklarasi tipe, dan T atau salah satu tipe dasarnya mengandung tipe terlapis yang dapat diakses yang memiliki nama I dan parameter tipe K, maka namespace_or_type_name mengacu pada tipe tersebut yang dibangun dengan argumen tipe yang diberikan. Jika ada lebih dari satu jenis tersebut, jenis yang dideklarasikan dalam jenis yang lebih turunan dipilih. Perhatikan bahwa anggota non-jenis (konstanta, bidang, metode, properti, pengindeks, operator, konstruktor instans, destruktor, dan konstruktor statis) dan jenis anggota dengan jumlah parameter jenis yang berbeda diabaikan saat menentukan arti namespace_or_type_name.
    • Jika langkah-langkah sebelumnya tidak berhasil maka, untuk setiap namespace N, dimulai dengan namespace tempat namespace_or_type_name terjadi, berlanjut dengan setiap namespace yang melingkupi (jika ada), dan diakhiri dengan namespace global, langkah-langkah berikut dievaluasi hingga entitas ditemukan:
      • Jika K adalah nol dan I adalah nama namespace layanan di N, maka:
        • Jika lokasi tempat namespace_or_type_name terjadi diapit oleh deklarasi namespace untuk N dan deklarasi namespace berisi extern_alias_directive atau using_alias_directive yang mengaitkan nama I dengan namespace atau jenis, atau deklarasi namespace apa pun untuk N dalam program berisi global_using_alias_directive yang mengaitkan nama I dengan namespace atau jenis, kemudian namespace_or_type_name ambigu dan terjadi kesalahan waktu kompilasi.
        • Jika tidak, namespace_or_type_name mengacu pada namespace bernama I di N.
      • Jika tidak, jika N berisi tipe yang dapat diakses yang memiliki nama I dan parameter jenis K, maka:
        • Jika K nol dan lokasi di mana namespace_or_type_name terjadi diapit oleh deklarasi namespace untuk N dan deklarasi namespace berisi extern_alias_directive atau using_alias_directive yang mengaitkan nama I dengan namespace atau jenis, atau deklarasi namespace apa pun untuk N dalam program berisi global_using_alias_directive yang mengaitkan nama I dengan namespace atau jenis,namespace_or_type_name ambigu dan terjadi kesalahan waktu kompilasi.
        • Jika tidak, namespace_or_type_name mengacu pada tipe yang telah dibentuk dengan argumen tipe yang diberikan.
      • Jika tidak, jika lokasi tempat namespace_or_type_name terjadi diapit oleh deklarasi namespace untuk N:
        • Jika K nol dan deklarasi namespace berisi extern_alias_directive atau using_alias_directive yang mengaitkan nama I dengan namespace atau jenis yang diimpor, atau deklarasi namespace apa pun untuk N dalam program berisi global_using_alias_directive yang mengaitkan nama I dengan namespace atau jenis yang diimpor, kemudian namespace_or_type_name mengacu pada namespace atau jenis tersebut.
        • Jika tidak, jika namespace dan tipe deklarasi yang diimpor oleh using_namespace_directivedan using_alias_directivedari deklarasi namespace dan namespace serta tipe deklarasi yang diimpor oleh global_using_namespace_directivedan global_using_static_directivedari deklarasi namespace manapun untuk N dalam program berisi persis satu tipe yang dapat diakses yang memiliki nama I dan parameter tipe K, kemudian namespace_or_type_name mengacu pada tipe tersebut yang dibangun dengan argumen tipe yang diberikan.
        • Namun jika namespace dan deklarasi jenis yang diimpor oleh using_namespace_directivedan using_alias_directivedari deklarasi namespace , serta namespace dan deklarasi jenis yang diimpor oleh global_using_namespace_directivedan global_using_static_directivedari setiap deklarasi namespace untuk N dalam program, berisi lebih dari satu jenis yang dapat diakses yang memiliki nama I dan parameter jenis K, maka namespace_or_type_name menjadi ambigu dan terjadi kesalahan.
    • Jika tidak, namespace_or_type_name tidak terdefinisi dan terjadi kesalahan waktu kompilasi.

Nama sederhana §12.8.4

Perubahan dilakukan pada aturan evaluasi simple_name sebagai berikut.

Ini adalah poin yang relevan dengan penambahan yang diusulkan (yang ditebalkan):

  • Jika tidak, untuk setiap namespace N, dimulai dengan namespace tempat simple_name terjadi, berlanjut dengan setiap namespace yang melingkupi (jika ada), dan diakhiri dengan namespace global, langkah-langkah berikut akan dievaluasi hingga entitas ditemukan:
    • Jika K adalah nol dan I adalah nama namespace layanan di N, maka:
      • Jika lokasi tempat simple_name terjadi diapit oleh deklarasi namespace untuk N dan deklarasi namespace berisi extern_alias_directive atau using_alias_directive yang mengaitkan nama I dengan namespace atau jenis, atau deklarasi namespace apa pun untuk N dalam program berisi global_using_alias_directive yang mengaitkan nama I dengan namespace atau jenis, kemudian simple_name ambigu dan terjadi kesalahan waktu kompilasi.
      • Jika tidak, simple_name mengacu pada namespace bernama I di N.
    • Jika tidak, jika N berisi tipe yang dapat diakses yang memiliki nama I dan parameter jenis K, maka:
      • Jika K nol dan lokasi tempat simple_name muncul diapit oleh deklarasi namespace untuk N dan deklarasi namespace berisi extern_alias_directive atau using_alias_directive yang mengaitkan nama I dengan namespace atau tipe, atau deklarasi namespace apa pun untuk N dalam program berisi global_using_alias_directive yang mengaitkan nama I dengan namespace atau tipe, maka simple_name ambigu dan terjadi kesalahan waktu kompilasi.
      • Jika tidak, namespace_or_type_name mengacu pada tipe yang telah dibentuk dengan argumen tipe yang diberikan.
    • Jika tidak, jika lokasi di mana simple_name terjadi berada dalam deklarasi namespace untuk N:
      • Jika K nol dan deklarasi namespace berisi extern_alias_directive atau using_alias_directive yang mengaitkan nama I dengan namespace atau jenis yang diimpor, atau deklarasi namespace apa pun untuk N dalam program berisi global_using_alias_directive yang mengaitkan nama I dengan namespace atau jenis yang diimpor, kemudian simple_name mengacu pada namespace atau jenis tersebut.
      • Jika tidak, jika namespace dan deklarasi tipe yang diimpor oleh using_namespace_directivedan using_static_directivedari deklarasi namespace dan namespace serta deklarasi tipe yang diimpor oleh global_using_namespace_directivedan global_using_static_directivedari deklarasi namespace apa pun untuk N dalam program berisi tepat satu tipe yang dapat diakses atau anggota statis bukan-ekstensi yang memiliki nama I dan K parameter tipe, kemudian simple_name mengacu pada tipe atau anggota yang dibangun dengan argumen tipe yang diberikan.
      • Jika tidak, jika namespace dan jenis yang diimpor oleh using_namespace_directivedari deklarasi namespace , serta namespace dan jenis deklarasi yang diimpor oleh global_using_namespace_directivedan global_using_static_directivedari deklarasi namespace mana pun untuk N dalam program, berisi lebih dari satu jenis yang dapat diakses atau anggota statis metode non-ekstensi yang memiliki nama I dan parameter jenis K, maka simple_name menjadi ambigu dan terjadi kesalahan.

Pemanggilan metode ekstensi §12.8.10.3

Perubahan dilakukan pada algoritma untuk menemukan type_nameC terbaik sebagai berikut. Ini adalah poin yang relevan dengan penambahan yang diusulkan (yang ditebalkan):

  • Dimulai dengan deklarasi namespace terdekat yang tertutup, berlanjut dengan setiap deklarasi namespace penutup, dan berakhir dengan unit kompilasi yang mengandung, upaya berturut-turut dilakukan untuk menemukan kumpulan kandidat metode ekstensi.
    • Jika namespace atau unit kompilasi yang diberikan langsung mengandung deklarasi tipe non-generik Ci dengan metode ekstensi yang memenuhi kriteria Mj, maka set metode ekstensi tersebut adalah set kandidat.
    • Jika jenis Ci diimpor oleh using_static_declarations dan langsung dideklarasikan dalam namespace yang diimpor oleh using_namespace_directivedi namespace yang diberikan atau unit kompilasi dan, jika unit kompilasi yang mengandung tercapai, diimpor oleh global_using_static_declarations dan langsung dideklarasikan dalam namespace yang diimpor oleh global_using_namespace_directivedalam program yang secara langsung berisi metode ekstensi yang memenuhi syarat Mj, maka set metode ekstensi tersebut adalah set kandidat.

Unit kompilasi §14.2

compilation_unit menentukan struktur keseluruhan file sumber. Sebuah unit kompilasi terdiri dari nol atau lebih global_using_directivediikuti dengan nol atau lebih using_directivediikuti dengan nol atau lebih global_attributes diikuti dengan nol atau lebih namespace_member_declaration.

compilation_unit
    : extern_alias_directive* global_using_directive* using_directive* global_attributes? namespace_member_declaration*
    ;

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

global_using_directiveunit kompilasi memengaruhi global_attributes dan namespace_member_declarationpada semua unit kompilasi dalam program.

Alias ekstern §14,4

Cakupan extern_alias_directive melewati global_using_directive,using_directive, global_attributes, dan namespace_member_declarationdari unit kompilasi atau isi namespace yang langsung berisi.

Menggunakan arahan alias §14.5.2

Urutan di mana using_alias_directiveditulis tidak memiliki signifikansi, dan 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, dan, jika using_alias_directive segera terkandung dalam unit kompilasi, tidak terpengaruh oleh global_using_directivedalam program. Dengan kata lain, namespace_or_type_name dari using_alias_directive diselesaikan seolah-olah unit kompilasi atau isi ruang nama yang segera mengandung tidak memiliki using_directives dan, jika using_alias_directive segera terkandung dalam unit kompilasi, program tidak memiliki global_using_directives. Namun, using_alias_directive dapat dipengaruhi oleh extern_alias_directiveyang ada di dalam unit kompilasi atau badan namespace yang langsung mengandungnya.

Global Menggunakan arahan alias

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

global_using_alias_directive
    : 'global' 'using' identifier '=' namespace_or_type_name ';'
    ;

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.

Pengidentifikasi dari *global_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 penulisan global_using_alias_directivetidak 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_name dari global_using_alias_directive diselesaikan seolah-olah unit kompilasi terdekat tidak mempertimbangkan using_directivedan seluruh program yang mengandung tidak mempertimbangkan global_using_directive. Namun, global_using_alias_directive mungkin dipengaruhi oleh extern_alias_directivedalam unit kompilasi yang langsung mengandungnya.

global_using_alias_directive dapat membuat alias untuk namespace atau jenis apa pun.

Mengakses namespace atau tipe melalui alias akan menghasilkan hasil yang sama persis dengan mengakses namespace atau tipe 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.

Penggunaan direktif namespace secara global

global_using_namespace_directive mengimpor tipe-tipe yang terdapat dalam suatu namespace ke dalam program, memungkinkan pengidentifikasi setiap tipe digunakan tanpa kualifikasi.

global_using_namespace_directive
    : 'global' 'using' namespace_name ';'
    ;

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, setiap nama yang diimpor oleh global_using_namespace_directive dalam program tertutupi oleh anggota dengan nama serupa di unit kompilasi tersebut.

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 sebuah global_using_namespace_directive diselesaikan dengan cara yang sama seperti namespace_or_type_name yang dirujuk oleh sebuah 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.

Penggunaan Arahan Statis Secara Global

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' type_name ';'
    ;

Dalam deklarasi anggota di dalam program yang mengandung global_using_static_directive, tipe bersarang yang dapat diakses dan anggota statis (kecuali metode ekstensi) yang terdapat langsung dalam deklarasi jenis yang bersangkutan dapat dirujuk secara langsung.

global_using_static_directive secara khusus tidak mengimpor metode ekstensi langsung sebagai metode statis, tetapi menjadikannya tersedia untuk pemanggilan metode ekstensi.

global_using_static_directive hanya mengimpor anggota dan tipe yang dideklarasikan langsung dalam tipe tersebut, bukan anggota dan tipe yang dideklarasikan dalam kelas dasar.

Ambiguitas antara beberapa global_using_namespace_directivedan global_using_static_directives dibahas di bagian untuk global_using_namespace_directive(di atas).

Anggota alias yang memenuhi syarat §14,8

Perubahan dilakukan pada algoritma yang menentukan arti qualified_alias_member sebagai berikut.

Ini adalah poin yang relevan dengan penambahan yang diusulkan (yang ditebalkan):

  • Jika tidak, dimulai dengan deklarasi namespace (§14.3) yang segera berisi qualified_alias_member (jika ada), melanjutkan dengan setiap deklarasi namespace yang mengapit (jika ada), dan diakhiri dengan unit kompilasi yang berisi qualified_alias_member. Langkah-langkah berikut dievaluasi hingga entitas ditemukan:

    • 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 mengaitkan N dengan jenis, maka qualified_alias_member tidak terdefinisi dan terjadi kesalahan waktu kompilasi.
    • Jika tidak, jika deklarasi namespace atau unit kompilasi berisi sebuah extern_alias_directive atau using_alias_directive yang mengaitkan N dengan namespace, *atau, ketika unit kompilasi tercapai dan program berisi sebuah global_using_alias_directive yang mengaitkan N dengan namespace, maka:
      • Jika namespace yang terkait dengan N berisi namespace bernama I dan K adalah nol, maka qualified_alias_member mengacu pada namespace tersebut.
      • Jika tidak, jika namespace yang terkait dengan N berisi jenis non-generik bernama I dan K adalah nol, maka qualified_alias_member mengacu pada jenis tersebut.
      • Jika tidak, jika namespace yang terkait dengan N berisi tipe bernama I yang memiliki parameter tipe K, 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.