2009-02-09 14 views

Respuesta

64

¡El desempaquetado solo funciona si el tipo es idéntico! No puede deseleccionar un object que no contiene el valor objetivo. Lo que necesita es algo a lo largo de las líneas de

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

Esto se ve si el valor es apta para su procesamiento como decimal. En caso afirmativo, asígnelo al result; si no asigne null. El siguiente código hace aproximadamente la misma y podría ser más fácil de entender para las personas que no están familiarizadas con el operador condicional ?::

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

No utilizaría la palabra "idéntico" aquí.Por ejemplo, puede desagrupar entre los tipos enum y su tipo subyacente, T y T ?, y algunos otros casos extraños IIRC. El CLR es más permisivo de lo que uno podría esperar. –

+0

(Pero sí, no debe esperar que unboxing analice una cadena :) –

+0

@Jon: ¿tiene una mejor formulación? Sin eso, voy a copiar tu comentario en mi respuesta porque expresa la advertencia muy bien. –

2

y si se utiliza decimal? temp = (decimal?)value;

+0

que no funciona. No puedo explicar por qué. En el modo de depuración, Visual Studio quiere mostrar el desmontaje ... – Natrium

+1

Eso es muy extraño porque funciona bien de mi lado ..... – StevenMcD

+0

No funcionará si value contiene una instancia de cadena. Debería funcionar si contiene una instancia de decimal. – pauloya

5

se debe analizar el decimal. Pero si usted quiere que su decimal a ser nula cuando la cadena no es correcta, utilice TryParse:

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

De esta manera se evitará excepciones al analizar cadenas enferma formateados.

Casi todos los tipos primitivos proporcionan métodos Parse y TryParse para convertir de cadena.

También se recomienda pasar un cultivo para el argumento de proveedor al método para evitar problemas con el separador decimal. Si está leyendo desde otro sistema, CultureInfo.InvariantCulture es probablemente el camino a seguir (pero no es el predeterminado).

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

Había olvidado el molde (decimal?) Para nulo ... lo siento, pero la parte de cultura sigue siendo importante. – thinkbeforecoding

+3

Esta respuesta es incorrecta ya que la asignación de 'valor' a 'temperatura' no funcionará. Debería ser ? parsedValue: (decimal?) null; – offner

1

Si no desea analizar cadenas, pero desea asegurarse de que recibe cualquiera null, un decimal o anulable decimal, entonces se podría hacer algo como esto:

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

Usted podría haga que devuelva nulo en la última línea en su lugar si desea evitar excepciones, aunque esto no distinguiría entre valores nulos reales y malos lanzamientos.

Tenga en cuenta que debe utilizar el operador "es", ya que el operador "como" no funciona en los tipos de valores, y la conversión sin comprobación puede arrojar una InvalidCastException.

También puede hacer que sea un método de extensión:

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

Y utilizar de esta manera:

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

Esto ayudará a evitar las advertencias sobre los contratos código de referencias nulas unboxing.

+0

¿Has probado tu método de extensión? Lo intenté y obtuve una NullReferenceException para un valor doble válido que necesitaba ser convertido a decimal numerable – Shiva

+0

@Shiva El método de extensión no está destinado a los dobles, ya que dice en la primera línea: "que recibe nulo, un decimal o un decimal nulo " –