Trasmetti l’object al decimale? (decimale annullabile)

Se hai questo nel setter di una proprietà:

decimal? temp = value as decimal?; 

value = “90”

Ma dopo il cast, temp è nullo

Qual è il modo corretto di fare questo cast?

Unboxing funziona solo se il tipo è identico! Non è ansible annullare la chiusura di un object che non contiene il valore di destinazione. Ciò di cui hai bisogno è qualcosa sulla falsariga di

 decimal tmpvalue; decimal? result = decimal.TryParse((string)value, out tmpvalue) ? tmpvalue : (decimal?)null; 

Questo controlla se il valore è analizzabile come decimal . Se sì, assegnalo al result ; altrimenti assegnare null . Il seguente codice fa approssimativamente lo stesso e potrebbe essere più facile da capire per le persone che non hanno familiarità con l’operatore condizionale ?: ::

 decimal tmpvalue; decimal? result = null; if (decimal.TryParse((string)value, out tmpvalue)) result = tmpvalue; 

dovresti analizzare il decimale. Ma se vuoi che il tuo decimale sia nullo quando la stringa non è corretta, usa TryParse:

 decimal parsedValue; decimal? temp = decimal.TryParse(value, out parsedValue) ? value : (decimal?)null; 

In questo modo eviterai le eccezioni mentre analizzi le stringhe mal formattate.

Quasi tutti i tipi primitivi forniscono metodi Parse e TryParse per la conversione da stringa.

Si consiglia inoltre di passare una cultura per l’argomento provider al metodo per evitare problemi con il separatore decimale. Se stai leggendo da un altro sistema, CultureInfo.InvariantCulture è probabilmente la strada da percorrere (ma non è l’impostazione predefinita).

 bool TryParse(string s, NumberStyles style, IFormatProvider provider, out decimal result) 

e se usi il decimal? temp = (decimal?)value; decimal? temp = (decimal?)value;

Se non vuoi analizzare le stringhe, ma vuoi assicurarti di ricevere null , un decimal o un decimal annullabile, puoi fare qualcosa del genere:

 public static Nullable Convert(object input) where T : struct { if (input == null) return null; if (input is Nullable || input is T) return (Nullable)input; throw new InvalidCastException(); } 

Si potrebbe rendere nullo di ritorno sull’ultima riga se si desidera evitare le eccezioni, anche se ciò non farebbe distinzione tra valori nulli reali e caste errate.

Si noti che è necessario utilizzare l’operatore “is”, poiché l’operatore “as” non funziona sui tipi di valore e il casting senza controllo può generare una InvalidCastException.

Potresti anche renderlo un metodo di estensione:

 public static class ObjectExtensions { public static Nullable ToNullable(this object input) where T : struct { if (input == null) return null; if (input is Nullable || input is T) return (Nullable)input; throw new InvalidCastException(); } } 

E usalo in questo modo:

 object value = 123.45m; decimal? dec = value.ToNullable(); 

Ciò consentirà di evitare avvisi sul contratto del codice relativi ai riferimenti null unboxing.