Come convertire C # nullable int in int


484

Come faccio a convertire un nullable intin un int? Supponiamo di avere 2 tipi di int come di seguito:

int? v1;  
int v2; 

Voglio assegnare v1il valore a v2. v2 = v1;causerà un errore. Come posso convertire v1in v2?


Qual è il comportamento desiderato quando v1è null?
Solomon Ucko,

Risposte:


637

Le altre risposte finora sono tutte corrette; Volevo solo aggiungere un altro che è leggermente più pulito:

v2 = v1 ?? default(int);

Qualsiasi Nullable<T>è implicitamente convertibile in suo T, A condizione che l'intera espressione valutata non possa mai tradursi in un'assegnazione nulla a un ValueType. Quindi, l'operatore a coalescenza nulla ??è solo zucchero di sintassi per l'operatore ternario:

v2 = v1 == null ? default(int) : v1;

... che è a sua volta zucchero di sintassi per un if / else:

if(v1==null)
   v2 = default(int);
else
   v2 = v1;

Inoltre, a partire da .NET 4.0 Nullable<T>ha un metodo "GetValueOrDefault ()", che è un getter null-safe che fondamentalmente esegue la coalescenza null mostrata sopra, quindi funziona anche:

v2 = v1.GetValueOrDefault();

4
È default(int)davvero necessario? Cosa c'è di sbagliato in un semplice 0?
Cole Johnson,

4
Funzionerebbe per questo esempio, ma nel caso generale si consiglia di utilizzare defaultdove appropriato. Zero non è sempre valido come valore, tanto meno il valore predefinito, quindi se lo sostituisci intcon un generico Tscoprirai che il mio codice funziona mentre zero no. In alcune future versioni di framework, defaultpotrebbe anche diventare sovraccaricabile; se e quando ciò accadrà, il codice che utilizza il default sarà facilmente in grado di trarne vantaggio, mentre dovranno essere cambiate assegnazioni esplicite nulle o zero.
KeithS

5
Questo dovrebbe arrivare in cima: .NET 4.0, Nullable <T> ha un "GetValueOrDefault ()"
RandomHandle,

Grazie per essere tornato a modificarlo con GetValueOrDefault!
CindyH,

Si consiglia di fare attenzione con DateTime quando si utilizza l'impostazione predefinita. Ciò potrebbe inserire la data predefinita anziché vuota.
Ranch Camal,


92

È possibile utilizzare la proprietà Value per l'assegnazione.

v2 = v1.Value;

8
Inoltre, se non si è sicuri che v1 contenga null, è possibile utilizzare l'operatore null coalescing per impostare un valore di fallback. Ad esempio v2 = v1 ?? 0;
Arjen,

12
E assicurati di controllare v1.HasValueprima.
Yuck,

3
MSDN dice che questo genererà un'eccezione se lo v1è null. Secondo me, questa non è una risposta corretta.
Ventiseis,

6
@ventiseis Penso che sia un comportamento desiderabile - sono sorpreso che molte delle altre risposte siano ok con la conversione silenziosa di un valore null in 0. Se stai assegnando un tipo nullable a un tipo non nullable, dovresti essere sicuro che il valore non è effettivamente nullo. OP non ha detto "Voglio assegnare v1 a v2, o 0 se v1 è null", ma è quello che tutti sembravano assumere
Michael Mrozek,


49

Se sai che v1ha un valore, puoi utilizzare la Valueproprietà:

v2 = v1.Value;

L'uso del GetValueOrDefaultmetodo assegnerà il valore se ce n'è uno, altrimenti l'impostazione predefinita per il tipo o un valore predefinito specificato:

v2 = v1.GetValueOrDefault(); // assigns zero if v1 has no value

v2 = v1.GetValueOrDefault(-1); // assigns -1 if v1 has no value

È possibile utilizzare la HasValueproprietà per verificare se v1ha un valore:

if (v1.HasValue) {
  v2 = v1.Value;
}

Esiste anche il supporto linguistico per il GetValueOrDefault(T)metodo:

v2 = v1 ?? -1;

Non utilizzare il valore senza prima controllare per vedere se esiste un valore. Usa il ?? operatore invece.
Peter,

45

Non puoi farlo se v1 è null, ma puoi verificare con un operatore.

v2 = v1 ?? 0;

28

GetValueOrDefault()

recupera il valore dell'oggetto. Se è null, restituisce il valore predefinito di int, che è 0.

Esempio:

v2= v1.GetValueOrDefault();


21

Se il valore predefinito per un determinato tipo è un risultato accettabile:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

Se si desidera un valore predefinito diverso quando il risultato non è definito:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

Se si desidera solo restituire il valore (indipendentemente dal fatto che il metodo non sia riuscito o meno):

v2 = v1.GetValueOrDefault();


.NET 4.7.2 .: GetValueOrDefault()restituisce il valore del campo senza alcun controllo.


15

Per quanto mi riguarda, la soluzione migliore sta usando il GetValueOrDefault()metodo.

v2 = v1.GetValueOrDefault();

questo mi è stato di grande aiuto
Liakat


10

è possibile con v2 = Convert.ToInt32(v1);


Funzionerà tecnicamente, ma altre tecniche come HasValue / Value o GetValueOrDefault funzionano in modo molto più efficiente.
Brandon Barkley,


9

Una semplice conversione tra v1e v2non è possibile perché v1ha un dominio di valori più grande di v2. È tutto ciò che v1può contenere più lo nullstato. Per convertire è necessario indicare esplicitamente quale valore intverrà utilizzato per mappare lo nullstato. Il modo più semplice per farlo è l' ??operatore

v2 = v1 ?? 0;  // maps null of v1 to 0

Questo può essere fatto anche in forma lunga

int v2;
if (v1.HasValue) {
  v2 = v1.Value;
} else {
  v2 = 0;
}

9

A seconda del contesto di utilizzo, è possibile utilizzare la funzione di corrispondenza dei motivi di C # 7:

int? v1 = 100;
if (v1 is int v2)
{
    Console.WriteLine($"I'm not nullable anymore: {v2}");
}

MODIFICARE:

Dal momento che alcune persone effettuano il downvoting senza lasciare una spiegazione, vorrei aggiungere alcuni dettagli per spiegare la logica per includere questo come soluzione praticabile.

  • La corrispondenza dei modelli di C # 7 ora ci consente di controllare il tipo di un valore e di lanciarlo implicitamente. Nel frammento precedente, la condizione if passerà solo quando il valore memorizzato v1è compatibile con il tipo per il tipo v2, che in questo caso lo è int. Ne consegue che quando il valore per v1è null, la condizione if fallirà poiché null non può essere assegnato a un int. Più propriamente, nullnon è un int.

  • Vorrei sottolineare che questa soluzione potrebbe non essere sempre la scelta ottimale. Come suggerisco, credo che ciò dipenderà dal contesto di utilizzo esatto dello sviluppatore. Se hai già un int?e vuoi operare in modo condizionale sul suo valore if-and-only-se il valore assegnato non è nullo (questa è l'unica volta in cui è sicuro convertire un nullable in un int normale senza perdere informazioni), quindi la corrispondenza dei modelli è forse uno dei modi più concisi per farlo.


La necessità di introdurre un nuovo nome di variabile è sfortunata, ma questa è la soluzione migliore (più sicura) se non esiste un valore predefinito, poiché non esiste il rischio di refactoring accidentale dei HasValuecontrolli.
minexew,

Non vedo alcun vantaggio su questo metodo rispetto a v1.HasValue come controllo e quindi v1.Value per accedere al valore sottostante. Non vorrei sottovalutarlo, ma penso che questo problema sia già stato risolto e una nuova tecnica non aggiunga molta chiarezza al problema. L'ho anche considerato più lento dell'8-9%.
Brandon Barkley,

Grazie per il benchmarking, è bello sapere! In ogni caso, la differenza è nella migliore delle ipotesi marginale (a meno che non lo facciate in un momento critico, suppongo). Considero questo essere più "conciso" o possibilmente "idiomatico" poiché si basa sugli zuccheri sintattici contenuti nella lingua anziché sulle API. È un po 'soggettivo, ma forse è "più mantenibile". Anche se in realtà, mi piace questo approccio più che basarmi su un valore predefinito, come suggeriscono molte altre risposte.
Nicholas Miller,

3

Assegnerà il valore di v1a v2se non è null, altrimenti prenderà un valore predefinito come zero.

v2=v1??0

O sotto c'è l'altro modo di scriverlo.

v2 = v1.HasValue?v1:0


-1
 int v2= Int32.Parse(v1.ToString());

5
Mentre questo codice può rispondere alla domanda, fornendo un contesto aggiuntivo riguardo al perché e / o al modo in cui questo codice risponde alla domanda migliora il suo valore a lungo termine.
Xiaia

1
È meglio utilizzare il modo "best practice" per scartare gli opzionali, invece di usare trucchi subdoli. Vedere docs.microsoft.com/en-us/dotnet/csharp/language-reference/… come riferimento
lorg

Quando rispondi a una domanda di otto anni con quindici risposte esistenti, è importante spiegare a quale nuovo aspetto della domanda si rivolge la tua risposta e notare se il passare del tempo ha cambiato la risposta. Le risposte solo al codice possono quasi sempre essere migliorate con l'aggiunta di alcune spiegazioni.
Jason Aller il
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.