Bagikan melalui


Ekspresi Kondisional Target-Typed

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 rapat desain bahasa terkait (LDM) .

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

Masalah juara: https://github.com/dotnet/csharplang/issues/2460

Konversi Ekspresi Bersyarat

Untuk sebuah ekspresi bersyarat c ? e1 : e2, saat

  1. tidak ada jenis umum untuk e1 dan e2, atau
  2. di mana jenis umum ada tetapi salah satu ekspresi e1 atau e2 tidak memiliki konversi implisit ke jenis tersebut

kami mendefinisikan konversi ekspresi kondisional implisit baru yang memungkinkan konversi implisit dari ekspresi kondisional ke jenis apa pun T di mana ada konversi dari ekspresi e1 ke T dan juga dari e2 ke T. Ini adalah kesalahan jika ekspresi bersyarat tidak memiliki jenis umum baik antara e1 dan e2 maupun tunduk pada konversi ekspresi bersyarat .

Konversi yang Lebih Baik dari Ekspresi

Kami berubah

Konversi yang lebih baik dari ekspresi

Mengingat konversi implisit yang mengonversi dari ekspresi menjadi jenis , dan konversi implisit yang mengonversi dari ekspresi ke jenis , adalah konversi yang lebih baik daripada jika tidak persis cocok dengan dan setidaknya salah satu penangguhan berikut:

  • E sama persis dengan T1 (§12.6.4.5)
  • T1 adalah target konversi yang lebih baik daripada T2 (§12.6.4.7)

ke

Konversi yang lebih baik dari ekspresi

Mengingat konversi implisit yang mengonversi dari ekspresi menjadi jenis , dan konversi implisit yang mengonversi dari ekspresi ke jenis , adalah konversi yang lebih baik daripada jika tidak persis cocok dengan dan setidaknya salah satu penangguhan berikut:

  • E sama persis dengan T1 (§12.6.4.5)
  • C1 bukan konversi ekspresi bersyarah dan C2 adalah konversi ekspresi bersyarah .
  • adalah target konversi yang lebih baik daripada (§12.6.4.7) dan baik maupun adalah konversi ekspresi bersyar atau tidak keduanya adalahkonversi ekspresi bersyarsial .

Ekspresi Tipe

Spesifikasi bahasa C# saat ini mengatakan

cast_expression dari bentuk , di mana adalah jenis dan adalah unary_expression, melakukan konversi eksplisit (§10.3) dari nilai ke tipe .

Dengan adanya konversi ekspresi kondisional , mungkin ada lebih dari satu kemungkinan konversi dari E ke T. Dengan penambahan konversi ekspresi bersyarat , kami lebih suka konversi lain ke konversi ekspresi bersyarat , dan menggunakan konversi ekspresi bersyarat hanya sebagai upaya terakhir.

Catatan Desain

Alasan perubahan ke konversi yang lebih baik dari ekspresi adalah untuk menangani kasus seperti ini:

M(b ? 1 : 2);

void M(short);
void M(long);

Pendekatan ini memang memiliki dua kelemahan kecil. Pertama, tidak sepenuhnya sama dengan ekspresi switch:

M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)

Ini masih merupakan perubahan mendasar, tetapi cakupannya cenderung tidak memengaruhi program yang ada.

M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.

M(short, short);
M(long, long);

Ini menjadi ambigu karena konversi ke long lebih baik untuk argumen pertama (karena tidak menggunakan konversi ekspresi bersyarat ), tetapi konversi ke short lebih baik untuk argumen kedua (karena short adalah target konversi lebih baik daripada long). Perubahan penting ini tampaknya kurang serius karena tidak mengubah perilaku program yang ada tanpa disadari.

Alasan catatan pada ekspresi pemeran adalah untuk menangani kasus seperti ini:

_ = (short)(b ? 1 : 2);

Program ini saat ini menggunakan konversi eksplisit dari int ke short, dan kami ingin mempertahankan arti bahasa program ini saat ini. Perubahan akan tidak dapat diobservasi pada runtime, tetapi dengan program berikut, perubahan akan dapat diamati:

_ = (A)(b ? c : d);

di mana c berjenis C, d berjenis D, dan ada konversi implisit yang ditentukan pengguna dari C ke D, dan konversi implisit yang ditentukan pengguna dari D ke A, dan konversi implisit yang ditentukan pengguna dari C ke A. Jika kode ini dikompilasi sebelum C# 9.0, ketika b benar, kita mengonversi dari c ke D maka ke A. Jika kita menggunakankonversi ekspresi kondisional , maka ketika benar, kita mengonversi dari ke secara langsung, yang menjalankan urutan kode pengguna yang berbeda. Oleh karena itu, kami memperlakukan konversi ekspresi kondisional sebagai upaya terakhir dalam casting, untuk mempertahankan perilaku yang ada.