Il tipo di espressione condizionale non può essere determinato perché non esiste una conversione implicita tra 'int' e <null>


Risposte:


338

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 xe yha un tipo, ed entrambi xe ysono 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 tipo Xe yha tipo Yallora

  • Se esiste una conversione implicita (§6.1) da Xa Y, ma non da Ya X, allora Yè il tipo dell'espressione condizionale.

  • Se esiste una conversione implicita (§6.1) da Ya X, ma non da Xa Y, allora Xè 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.


4
Buona citazione delle specifiche per illustrare il motivo per cui ciò accade: +1!
JerKimball,

7
Un'altra opzione è new int?()al posto di (int?)null.
Guvante,

1
Questo è anche il caso se si dispone di un tipo di campo di database nullable, ad esempio un DateTime nullable e si tenta di trasmettere i dati DateTime, quando richiesto(DateTime?)
Mike Upjohn

73

null non ha alcun tipo identificabile - ha solo bisogno di un piccolo stimolo per renderlo felice:

int? number = true ? 5 : (int?)null;

2
Oppure puoi farloint? number = true ? 5 : null as int?;
Brad M,

Bella risposta inchiodare il punto. Bella lettura correlata: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Benjamin Gruenbaum

Il problema non è che nullnon ha un tipo identificabile. Il problema è che non esiste una conversione implicita da nulla int. Dettagli qui .
Jason,

la cosa interessante è che int? number = true ? 5 : (int?)null;ed int? number = true ? (int?)5 : null;entrambi compiliamo !! Scratch, scratch
davidhq

2
Copro esattamente perché questo accade nella mia risposta .
Jason,

4

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>.


1

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;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.