Perché questo non si compila?
int? number = true ? 5 : null;
Il tipo di espressione condizionale non può essere determinato perché non esiste una conversione implicita tra 'int' e <null>
Perché questo non si compila?
int? number = true ? 5 : null;
Il tipo di espressione condizionale non può essere determinato perché non esiste una conversione implicita tra 'int' e <null>
Risposte:
La specifica (§7.14) dice che per l'espressione condizionale b ? x : y
, ci sono tre possibilità, entrambe x
ed y
entrambe hanno un tipo e sono soddisfatte alcune buone condizioni , solo una di x
e y
ha un tipo e determinate buone condizioni sono soddisfatte, o un errore di compilazione si verifica. Qui, "determinate buone condizioni" indicano che sono possibili determinate conversioni, di cui entreremo nei dettagli di seguito.
Passiamo ora alla parte germana delle specifiche:
Se solo uno di
x
ey
ha un tipo, ed entrambix
ey
sono implicitamente convertibili in quel tipo, allora quello è il tipo dell'espressione condizionale.
Il problema qui è che in
int? number = true ? 5 : null;
solo uno dei risultati condizionali ha un tipo. Qui x
è un int
letterale ed y
è null
che non ha un tipo e null
non è implicitamente convertibile in un int
1 . Pertanto, "determinate buone condizioni" non sono soddisfatte e si verifica un errore in fase di compilazione.
Ci sono due modi per aggirare questo:
int? number = true ? (int?)5 : null;
Qui siamo ancora nel caso in cui solo uno di x
e y
abbia un tipo. Si noti che null
ancora non ha ancora un tipo ma il compilatore non avrà alcun problema con questo perché (int?)5
e null
sono entrambi implicitamente convertibili in int?
(§6.1.4 e §6.1.5).
L'altro modo è ovviamente:
int? number = true ? 5 : (int?)null;
ma ora dobbiamo leggere una clausola diversa nelle specifiche per capire perché questo va bene:
Se
x
ha tipoX
ey
ha tipoY
allora
Se esiste una conversione implicita (§6.1) da
X
aY
, ma non daY
aX
, alloraY
è il tipo dell'espressione condizionale.Se esiste una conversione implicita (§6.1) da
Y
aX
, ma non daX
aY
, alloraX
è il tipo dell'espressione condizionale.Altrimenti, non è possibile determinare alcun tipo di espressione e si verifica un errore in fase di compilazione.
Qui x
è di tipo int
ed y
è di tipo int?
. Non esiste una conversione implicita da int?
a int
, ma esiste una conversione implicita da int
a int?
così è il tipo di espressione int?
.
1 : Nota inoltre che il tipo del lato sinistro viene ignorato nel determinare il tipo dell'espressione condizionale, qui una fonte comune di confusione.
new int?()
al posto di (int?)null
.
DateTime
, quando richiesto(DateTime?)
null
non ha alcun tipo identificabile - ha solo bisogno di un piccolo stimolo per renderlo felice:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;
ed int? number = true ? (int?)5 : null;
entrambi compiliamo !! Scratch, scratch
Come altri hanno già detto, il 5 è un int
e null
non può essere convertito implicitamente in int
.
Ecco altri modi per aggirare il problema:
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;
Inoltre, ovunque tu veda int?
, puoi anche usare Nullable<int>
.
In C# 9
questo è ora consentito il blog
Target digitato ?? e ?
A volte condizionale ?? e?: le espressioni non hanno un evidente tipo condiviso tra i rami. Tali casi falliscono oggi, ma C # 9.0 li consentirà se esiste un tipo di destinazione che entrambi i rami convertono in:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
O il tuo esempio:
// Allowed in C# 9.
int? number = true ? 5 : null;