Bagikan melalui


Ekspresi new yang bertipe target

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 dari 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/100

Ringkasan

Jangan memerlukan spesifikasi jenis untuk konstruktor ketika jenis diketahui.

Motivasi

Perbolehkan inisialisasi bidang tanpa menduplikasi jenis.

Dictionary<string, List<int>> field = new() {
    { "item1", new() { 1, 2, 3 } }
};

Izinkan menghilangkan tipe data ketika dapat disimpulkan dari penggunaannya.

XmlReader.Create(reader, new() { IgnoreWhitespace = true });

Menginstansiasi objek tanpa menyebutkan jenisnya secara eksplisit.

private readonly static object s_syncObj = new();

Spesifikasi

Bentuk sintaksis baru, target_typed_new dari object_creation_expression diterima di mana jenis bersifat opsional.

object_creation_expression
    : 'new' type '(' argument_list? ')' object_or_collection_initializer?
    | 'new' type object_or_collection_initializer
    | target_typed_new
    ;
target_typed_new
    : 'new' '(' argument_list? ')' object_or_collection_initializer?
    ;

Ekspresi target_typed_new tidak memiliki tipe. Namun, ada konversi pembuatan objek baru yang merupakan konversi implisit dari ekspresi, yang ada dari target_typed_new ke setiap jenis.

Mengingat jenis target T, jenis T0 adalah jenis dasar dari Tjika T adalah instance dari System.Nullable. Jika tidak, T0 adalah T. Arti ekspresi target_typed_new yang dikonversi ke jenis T sama dengan arti object_creation_expression terkait yang menentukan T0 sebagai jenis.

Ini adalah kesalahan saat waktu kompilasi jika target_typed_new digunakan sebagai operan operator unary atau biner, atau jika digunakan di mana ia tidak tunduk pada konversi pembuatan objek .

Masalah Terbuka: haruskah kami mengizinkan delegates dan tuples sebagai tipe target?

Aturan di atas mencakup delegat (tipe referensi) dan tuple (tipe struct). Meskipun kedua jenis tersebut bisa dibangun, jika jenisnya dapat disimpulkan, fungsi anonim atau literal tuple sudah bisa digunakan.

(int a, int b) t = new(1, 2); // "new" is redundant
Action a = new(() => {}); // "new" is redundant

(int a, int b) t = new(); // OK; same as (0, 0)
Action a = new(); // no constructor found

Lain-lain

Berikut ini adalah konsekuensi dari spesifikasi:

  • throw new() diperbolehkan (targetnya adalah jenis System.Exception)
  • Tipe target new tidak diizinkan dengan operator biner.
  • Ini tidak diizinkan ketika tidak ada jenis untuk ditargetkan: operator unari, kumpulan foreach, dalam using, dalam dekontruksi, dalam ekspresi await, sebagai properti jenis anonim (new { Prop = new() }), dalam pernyataan lock, dalam sizeof, dalam pernyataan fixed, dalam akses anggota (new().field), dalam operasi yang dikirim secara dinamis (someDynamic.Method(new())), dalam kueri LINQ, sebagai operan operator is, sebagai operan kiri operator ??, ...
  • Ini juga dilarang sebagai ref.
  • Jenis jenis berikut tidak diizinkan sebagai target konversi
    • jenis Enum:new() akan berfungsi (karena new Enum() bekerja untuk memberikan nilai default), tetapi new(1) tidak akan berfungsi karena jenis enum tidak memiliki konstruktor.
    • Jenis antarmuka: Ini akan berfungsi sama dengan ekspresi pembuatan yang sesuai untuk jenis COM.
    • Jenis array: array memerlukan sintaks khusus untuk menyediakan panjangnya.
    • dinamis: kami tidak mengizinkan new dynamic(), jadi kami tidak mengizinkan new() dengan dynamic sebagai jenis target.
    • tuple: Ini memiliki arti yang sama dengan pembuatan objek menggunakan tipe dasar.
    • Semua jenis lain yang tidak diizinkan dalam object_creation_expression juga dikecualikan, misalnya, jenis pointer.

Kekurangan

Ada beberapa kekhawatiran dengan new bertipe target membuat kategori baru dari perubahan yang mengganggu, tetapi kami sudah memilikinya dengan null dan default, dan hal itu belum menjadi masalah yang signifikan.

Alternatif

Sebagian besar keluhan tentang tipe yang terlalu panjang untuk diduplikasi dalam inisialisasi bidang adalah tentang argumen tipe bukan tipe itu sendiri, kita hanya dapat menyimpulkan argumen tipe seperti new Dictionary(...) (atau yang serupa) dan menyimpulkan argumen tipe secara lokal dari argumen atau inisialiasi koleksi.

Pertanyaan

  • Haruskah kita melarang penggunaan di pohon ekspresi? (tidak)
  • Bagaimana fitur berinteraksi dengan argumen dynamic? (tidak ada perlakuan khusus)
  • Bagaimana IntelliSense harus bekerja dengan new()? (hanya ketika ada satu tipe target)

Rapat Desain