Mengapa ini tidak dikompilasi?
int? number = true ? 5 : null;
Jenis ekspresi kondisional tidak dapat ditentukan karena tidak ada konversi implisit antara 'int' dan <null>
Mengapa ini tidak dikompilasi?
int? number = true ? 5 : null;
Jenis ekspresi kondisional tidak dapat ditentukan karena tidak ada konversi implisit antara 'int' dan <null>
Jawaban:
Spec (§7.14) mengatakan bahwa untuk ekspresi kondisional b ? x : y
, ada tiga kemungkinan, baik x
dan y
keduanya memiliki tipe dan kondisi baik tertentu terpenuhi, hanya satu dari x
dan y
memiliki tipe dan kondisi baik tertentu terpenuhi, atau kesalahan waktu kompilasi. terjadi. Di sini, "kondisi baik tertentu" berarti konversi tertentu dimungkinkan, yang akan kita bahas di bawah ini.
Sekarang, mari kita beralih ke bagian erat dari spec:
Jika hanya satu
x
dany
memiliki jenis, dan keduanyax
dany
secara implisit dapat dikonversi ke jenis itu, maka itu adalah jenis ekspresi kondisional.
Masalahnya di sini adalah bahwa di
int? number = true ? 5 : null;
hanya satu dari hasil bersyarat yang memiliki tipe. Berikut x
adalah int
literal, dan y
ini null
yang tidak tidak memiliki tipe dan null
tidak implisit dikonversi ke int
1 . Oleh karena itu, "kondisi baik tertentu" tidak terpenuhi, dan kesalahan waktu kompilasi terjadi.
Ada yang dua cara untuk melakukannya:
int? number = true ? (int?)5 : null;
Di sini kita masih dalam kasus di mana hanya satu x
dan y
memiliki tipe. Perhatikan bahwa null
masih belum memiliki tipe namun kompiler tidak akan memiliki masalah dengan ini karena (int?)5
dan null
keduanya secara implisit dapat dikonversi ke int?
(§6.1.4 dan §6.1.5).
Cara lainnya jelas:
int? number = true ? 5 : (int?)null;
tetapi sekarang kita harus membaca klausa yang berbeda dalam spesifikasi untuk memahami mengapa ini tidak apa-apa:
Jika
x
bertipeX
dany
bertipeY
maka
Jika konversi implisit (§6.1) ada dari
X
keY
, tetapi bukan dariY
keX
, makaY
adalah jenis ekspresi kondisional.Jika konversi implisit (§6.1) ada dari
Y
keX
, tetapi bukan dariX
keY
, makaX
adalah jenis ekspresi kondisional.Jika tidak, tidak ada tipe ekspresi yang dapat ditentukan, dan kesalahan waktu kompilasi terjadi.
Ini x
adalah tipe int
dan y
tipe int?
. Tidak ada konversi implisit dari int?
ke int
, tetapi ada konversi implisit dari int
ke int?
jadi jenis ungkapannya int?
.
1 : Catat lebih jauh bahwa tipe sisi kiri diabaikan dalam menentukan tipe ekspresi bersyarat, sumber kebingungan yang umum di sini.
new int?()
di tempat (int?)null
.
DateTime
, ketika itu diperlukan(DateTime?)
null
tidak memiliki tipe yang dapat diidentifikasi - hanya perlu sedikit dorongan untuk membuatnya senang:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;
dan int? number = true ? (int?)5 : null;
kompilasi keduanya !! Gores, gores
Seperti yang disebutkan orang lain, angka 5 adalah int
, dan null
tidak dapat dikonversi secara implisit int
.
Berikut adalah cara lain untuk mengatasi masalah ini:
int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
Juga, di mana pun Anda melihat int?
, Anda juga bisa menggunakan Nullable<int>
.
Dalam C# 9
hal ini sekarang diperbolehkan blog
Target diketik ?? dan?
Terkadang bersyarat ?? dan?: ekspresi tidak memiliki tipe bersama yang jelas antara cabang. Kasus seperti ini gagal hari ini, tetapi C # 9.0 akan memungkinkan mereka jika ada tipe target yang dikonversi oleh kedua cabang:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
Atau contoh Anda:
// Allowed in C# 9.
int? number = true ? 5 : null;