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.
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 ditangkap 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 .
Masalah utama: https://github.com/dotnet/csharplang/issues/5529
Ringkasan
Izinkan pengubah file pada deklarasi jenis tingkat atas. Jenis hanya ada dalam file di mana ia dideklarasikan.
// File1.cs
namespace NS;
file class Widget
{
}
// File2.cs
namespace NS;
file class Widget // different symbol than the Widget in File1
{
}
// File3.cs
using NS;
var widget = new Widget(); // error: The type or namespace name 'Widget' could not be found.
Motivasi
Motivasi utama kami berasal dari pembangkit kode sumber. Generator sumber berfungsi dengan menambahkan file ke kompilasi pengguna.
- File-file tersebut harus dapat berisi detail implementasi yang disembunyikan dari kompilasi lainnya, namun dapat digunakan di seluruh file tempat mereka dinyatakan.
- Kami ingin mengurangi kebutuhan generator untuk "mencari" nama jenis yang tidak akan bertabrakan dengan deklarasi dalam kode pengguna atau kode dari generator lain.
Desain terperinci
- Kami menambahkan pengubah
fileke set pengubah berikut: - Pengubah
filehanya dapat digunakan pada jenis tingkat atas.
Ketika suatu jenis memiliki pengubah file, itu dianggap sebagai tipe lokal berkas.
Aksesibilitas
Pengubah file tidak diklasifikasikan sebagai pengubah aksesibilitas. Tidak ada pengubah aksesibilitas yang dapat digunakan dalam kombinasi dengan file pada jenis.
file diperlakukan sebagai konsep independen dari aksesibilitas. Karena jenis file-lokal tidak dapat ditumpuk, hanya aksesibilitas default internal yang dapat digunakan dengan jenis file.
public file class C1 { } // error
internal file class C2 { } // error
file class C3 { } // ok
Penamaan
Implementasi menjamin bahwa jenis lokal file dalam file yang berbeda dengan nama yang sama akan berbeda dengan runtime. Aksesibilitas dan nama tipe dalam metadata ditentukan oleh implementasi. Tujuannya adalah untuk mengizinkan pengkompilasi untuk mengadopsi fitur batasan akses di masa mendatang dalam runtime yang cocok untuk fitur tersebut. Diharapkan bahwa dalam implementasi awal, aksesibilitas internal akan digunakan dan nama yang tidak dapat dibicarakan akan dihasilkan, yang tergantung pada file tempat jenis dideklarasikan.
Lookup
Kami mengubah bagian pencarian anggota sebagai berikut (teks baru dalam tebal):
- Selanjutnya, jika
Knol, semua jenis berlapis yang deklarasinya menyertakan parameter jenis akan dihapus. JikaKbukan nol, semua anggota dengan jumlah parameter jenis yang berbeda akan dihapus. KetikaKnol, metode yang memiliki parameter jenis tidak dihapus, karena proses inferensi jenis (ยง11,6,3) mungkin dapat menyimpulkan argumen jenis.- Selanjutnya, biarkan F menjadi unit kompilasi yang berisi ekspresi tempat pencarian anggota terjadi. Semua anggota yang merupakan jenis lokal file dan tidak dideklarasikan dalam F dihapus dari set.
- Berikutnya, jika kumpulan anggota yang dapat diakses berisi jenis file-lokal, semua anggota yang bukan jenis file-lokal dihapus dari set.
Komentar
Aturan ini melarang penggunaan tipe file-lokal di luar file tempat mereka dideklarasikan.
Aturan ini juga mengizinkan jenis lokal berkas untuk menurunkan namespace atau jenis non-lokal berkas:
// File1.cs
class C
{
public static void M() { }
}
// File2.cs
file class C
{
public static void M() { }
}
class Program
{
static void Main()
{
C.M(); // refers to the 'C' in File2.cs
}
}
Perhatikan bahwa kami tidak memperbarui bagian cakupan dari spesifikasi. Ini karena, sesuai dengan spesifikasi:
Cakupan dari sebuah nama adalah bagian dari teks program di mana kita dapat merujuk pada entitas yang dinyatakan oleh nama tersebut tanpa perlu kualifikasi lebih lanjut.
Akibatnya, cakupan hanya berdampak pada pencarian nama yang tidak memenuhi syarat. Ini bukan konsep yang tepat bagi kita untuk digunakan karena kita juga perlu memengaruhi pencarian nama yang memenuhi kriteria.
// File1.cs
namespace NS1
{
file class C
{
public static void M() { }
}
}
namespace NS2
{
class Program
{
public static void M()
{
C.M(); // error: C is not in scope
NS1.C.M(); // ok: C can be accessed through NS1.
}
}
}
// File2.cs
namespace NS1
{
class Program
{
C.M(); // error
NS1.C.M(); // error
}
}
Oleh karena itu, kami tidak menentukan fitur dalam hal cakupan jenis yang terkandung di dalamnya, melainkan sebagai "aturan pemfilteran" tambahan dalam pencarian anggota.
Atribut
Kelas file-lokal diizinkan menjadi jenis atribut, dan dapat digunakan sebagai atribut dalam jenis file-lokal dan jenis non-file-lokal, seolah-olah jenis atributnya adalah jenis non-file-lokal. Nama metadata dari jenis atribut file-local masih melalui strategi pembuatan nama yang sama dengan jenis file lokal lainnya. Ini berarti mendeteksi keberadaan tipe lokal file melalui nama string yang hard-coded kemungkinan besar tidak praktis, karena memerlukan ketergantungan pada strategi pembangkitan nama internal dari pengkompilasi, yang dapat berubah seiring waktu. Namun, mendeteksi melalui typeof(MyFileLocalAttribute) berfungsi.
using System;
using System.Linq;
file class MyFileLocalAttribute : Attribute { }
[MyFileLocalAttribute]
public class C
{
public static void Main()
{
var attribute = typeof(C).CustomAttributes.Where(attr => attr.AttributeType == typeof(MyFileLocalAttribute)).First();
Console.Write(attribute); // outputs the generated name of the file-local attribute type
}
}
Penggunaan dalam tanda tangan
Ada kebutuhan umum untuk mencegah jenis file-lokal muncul dalam parameter anggota, pengembalian, dan batasan parameter tipe di mana jenis file-lokal tersebut mungkin tidak berada dalam cakupan pada titik penggunaan anggota tersebut.
Perhatikan bahwa jenis lokal non-file diizinkan untuk mengimplementasikan antarmuka file-lokal, mirip dengan bagaimana jenis dapat menerapkan antarmuka yang kurang dapat diakses. Bergantung pada jenis yang ada di anggota antarmuka, itu dapat mengakibatkan pelanggaran aturan di bagian berikut.
Hanya izinkan penggunaan tanda tangan pada anggota tipe lokal-file
Mungkin cara paling sederhana untuk memastikan hal ini adalah dengan memberlakukan bahwa jenis file-lokal hanya dapat muncul dalam tanda tangan atau sebagai jenis dasar dari jenis lokal file lainnya:
file class FileBase
{
}
public class Derived : FileBase // error
{
private FileBase M2() => new FileBase() // error
}
file class FileDerived : FileBase // ok
{
private FileBase M2() => new FileBase(); // ok
}
Perhatikan bahwa ini membatasi penggunaan dalam implementasi eksplisit, meskipun penggunaan tersebut aman. Kami melakukan ini untuk menyederhanakan aturan untuk iterasi awal fitur.
file interface I
{
void M(I i);
}
class C : I
{
void I.M(I i) { } // error
}
global using static
Ini adalah kesalahan saat kompilasi untuk menggunakan jenis file lokal dalam direktif global using static, yaitu sebagai berikut.
global using static C; // error
file class C
{
public static void M() { }
}
Implementasi/penimpaan
deklarasi jenis lokal file dapat menerapkan antarmuka, mengambil alih metode virtual, dll. sama seperti deklarasi jenis reguler.
file struct Widget : IEquatable<Widget>
{
public bool Equals(Widget other) => true;
}
C# feature specifications