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 xed yentrambe hanno un tipo e sono soddisfatte alcune buone condizioni , solo una di xe yha 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
xeyha un tipo, ed entrambixeysono 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 intletterale ed yè nullche non ha un tipo e nullnon è implicitamente convertibile in un int1 . 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 xe yabbia un tipo. Si noti che null ancora non ha ancora un tipo ma il compilatore non avrà alcun problema con questo perché (int?)5e nullsono 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
xha tipoXeyha tipoYallora
Se esiste una conversione implicita (§6.1) da
XaY, ma non daYaX, alloraYè il tipo dell'espressione condizionale.Se esiste una conversione implicita (§6.1) da
YaX, ma non daXaY, 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 inted yè di tipo int?. Non esiste una conversione implicita da int?a int, ma esiste una conversione implicita da inta 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 inte nullnon 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# 9questo è 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;