Jenis ekspresi kondisional tidak dapat ditentukan karena tidak ada konversi implisit antara 'int' dan <null>

Jawaban:

338

Spec (§7.14) mengatakan bahwa untuk ekspresi kondisional b ? x : y, ada tiga kemungkinan, baik xdan ykeduanya memiliki tipe dan kondisi baik tertentu terpenuhi, hanya satu dari xdan ymemiliki 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 xdan ymemiliki jenis, dan keduanya xdan ysecara 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 xadalah intliteral, dan yini nullyang tidak tidak memiliki tipe dan nulltidak implisit dikonversi ke int1 . 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 xdan ymemiliki tipe. Perhatikan bahwa null masih belum memiliki tipe namun kompiler tidak akan memiliki masalah dengan ini karena (int?)5dan nullkeduanya 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 xbertipe Xdan ybertipe Ymaka

  • Jika konversi implisit (§6.1) ada dari Xke Y, tetapi bukan dari Yke X, maka Yadalah jenis ekspresi kondisional.

  • Jika konversi implisit (§6.1) ada dari Yke X, tetapi bukan dari Xke Y, maka Xadalah jenis ekspresi kondisional.

  • Jika tidak, tidak ada tipe ekspresi yang dapat ditentukan, dan kesalahan waktu kompilasi terjadi.

Ini xadalah tipe intdan ytipe int?. Tidak ada konversi implisit dari int?ke int, tetapi ada konversi implisit dari intke 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.

jason
sumber
4
Mengutip spec yang baik untuk menggambarkan mengapa hal ini terjadi - +1!
JerKimball
7
Opsi lain ada new int?()di tempat (int?)null.
Guvante
1
Ini juga merupakan kasus jika Anda memiliki tipe bidang basis data yang dapat dibatalkan, misalnya DateTime yang dapat dibatalkan dan Anda mencoba dan melemparkan data ke DateTime, ketika itu diperlukan(DateTime?)
Mike Upjohn
73

null tidak memiliki tipe yang dapat diidentifikasi - hanya perlu sedikit dorongan untuk membuatnya senang:

int? number = true ? 5 : (int?)null;
Marc Gravell
sumber
2
Atau Anda dapat melakukannyaint? number = true ? 5 : null as int?;
Brad M
Jawaban yang bagus memaku intinya. Bacaan terkait yang menyenangkan: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Benjamin Gruenbaum
Masalahnya bukan yang nulltidak memiliki tipe yang dapat diidentifikasi. Masalahnya adalah tidak ada konversi tersirat dari nullke int. Detail di sini .
jason
yang menarik adalah itu int? number = true ? 5 : (int?)null;dan int? number = true ? (int?)5 : null;kompilasi keduanya !! Gores, gores
davidhq
2
Aku menutupi persis mengapa hal ini terjadi di saya jawabannya .
jason
4

Seperti yang disebutkan orang lain, angka 5 adalah int, dan nulltidak 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>.

Andrew
sumber
1

Dalam C# 9hal 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;
WBuck
sumber