Bagikan melalui


Izinkan menggunakan direktif alias untuk mereferensikan jenis apa pun

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 rapat terkait 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/8645

Ringkasan

Lunakkan using_alias_directive (§13.5.2) untuk memungkinkannya menunjuk pada jenis apa pun, bukan hanya jenis yang diberi nama. Ini akan mendukung jenis yang tidak diizinkan saat ini, seperti jenis tuple, tipe pointer, jenis array, dll. Misalnya, ini sekarang akan diizinkan.

using Point = (int x, int y);

Motivasi

Sejak lama, C# telah memiliki kemampuan untuk memperkenalkan alias untuk namespace dan jenis bernama (kelas, delegasi, antarmuka, record, dan struktur). Ini bekerja dengan baik serta menyediakan sarana untuk memperkenalkan nama yang tidak bertentangan dalam kasus di mana nama normal yang ditarik dari using_directivemungkin ambigu, dan memungkinkan cara untuk memberikan nama yang lebih sederhana saat berhadapan dengan jenis generik yang kompleks. Namun, munculnya simbol tipe kompleks tambahan dalam bahasa pemrograman telah menyebabkan lebih banyak penggunaan yang muncul di mana alias akan berharga tetapi saat ini tidak diizinkan. Misalnya, baik tuple maupun penunjuk fungsi seringkali dapat memiliki bentuk tekstual yang besar dan kompleks yang bisa sangat merepotkan untuk terus menerus ditulis dan menjadi beban untuk dibaca. Alias akan membantu dalam kasus ini dengan memberikan nama singkat yang disediakan pengembang yang kemudian dapat digunakan sebagai pengganti bentuk struktural penuh tersebut.

Desain terperinci

Kami akan mengubah tata bahasa using_alias_directive dengan demikian:

using_alias_directive
-    : 'using' identifier '=' namespace_or_type_name ';'
+    : 'using' identifier '=' (namespace_name | type) ';'
    ;

Anotasi nullability jenis referensi paling atas tidak diperbolehkan.

Menariknya, sebagian besar bahasa spesifikasi dalam §13.5.2 tidak perlu berubah. Sebagian besar bahasa di dalamnya sudah mengacu pada 'namespace atau jenis', misalnya:

using_alias_directive memperkenalkan pengidentifikasi yang berfungsi sebagai alias untuk namespace atau tipe dalam unit kompilasi atau tubuh namespace yang langsung menaunginya.

Ini tetap benar, hanya saja sekarang tata bahasanya memungkinkan 'jenis' untuk menjadi tipe apa pun, bukan terbatas pada himpunan yang sebelumnya diizinkan oleh namespace_or_type_name.

Bagian yang perlu diperbarui adalah:

- The order in which using_alias_directives are written has no significance, and resolution of the namespace_or_type_name referenced by a using_alias_directive is not affected by the using_alias_directive itself or by other using_directives in the immediately containing compilation unit or namespace body. In other words, the namespace_or_type_name of a using_alias_directive is resolved as if the immediately containing compilation unit or namespace body had no using_directives. A using_alias_directive may however be affected by extern_alias_directives in the immediately containing compilation unit or namespace body. In the example
+ The order in which using_alias_directives are written has no significance, and resolution of the `(namespace_name | type)` referenced by a using_alias_directive is not affected by the using_alias_directive itself or by other using_directives in the immediately containing compilation unit or namespace body. In other words, the `(namespace_name | type)` of a using_alias_directive is resolved as if the immediately containing compilation unit or namespace body had no using_directives. A using_alias_directive may however be affected by extern_alias_directives in the immediately containing compilation unit or namespace body. In the example
- The namespace_name referenced by a using_namespace_directive is resolved in the same way as the namespace_or_type_name referenced by a using_alias_directive. Thus, using_namespace_directives in the same compilation unit or namespace body do not affect each other and can be written in any order.
+ The namespace_name referenced by a using_namespace_directive is resolved in the same way as the namespace_or_type_name referenced by a using_alias_directive. Thus, using_namespace_directives in the same compilation unit or namespace body do not affect each other and can be written in any order.
+ It is illegal for a using alias type to be a nullable reference type.

    1. `using X = string?;` is not legal.
    2. `using X = List<string?>;` is legal.  The alias is to `List<...>` which is itself not a nullable reference type itself, even though it contains one as a type argument.
    3. `using X = int?;` is legal.  This is a nullable *value* type, not a nullable *reference* type.

Mendukung alias ke tipe yang berisi pointer.

Konteks baru tidak aman ditambahkan melalui kata kunci 'tidak aman' opsional dalam produksi `using_alias_directive`:

using_alias_directive
+    : 'using' 'unsafe'? identifier '=' (namespace_name | type) ';'
    ;
    
using_static_directive
+    : 'using' 'static' 'unsafe'? type_name ';'
    ;

+ 'unsafe' can only be used with an using_alias_directive or using_static_directive, not a using_directive.
+ The 'unsafe' keyword present in a 'using_alias_directive' causes the entire textual extent of the 'type' portion (not the 'namespace_name' portion) to become an unsafe context. 
+ The 'unsafe' keyword present in a 'using_static_directive' causes the entire textual extent of the 'type_name' portion to become an unsafe context.