2008-09-14 17 views
15

Esto puede parecer rudimentario para algunos, pero esta pregunta me ha estado fastidiando y mientras escribo un código, pensé que podría preguntar.C# Casting vs. Parse

¿Cuál de los siguientes es mejor código en C# y por qué?

((DateTime)g[0]["MyUntypedDateField"]).ToShortDateString() 

o

DateTime.Parse(g[0]["MyUntypedDateField"].ToString()).ToShortDateString() 

En última instancia, ¿es mejor para emitir o para analizar? ¡Gracias a todos!

Respuesta

12

Si g [0] ["MyUntypedDateField"] es realmente un objeto DateTime, entonces el elenco es la mejor opción. Si no es realmente un DateTime, entonces no tienes más remedio que utilizar el Parse (obtendrías una InvalidCastException si intentas usar el elenco)

+2

Cuando el objeto no es un DateTime, no use Parse, más bien use ParseExact y especifique el formato de fecha y hora esperado, para evitar depender de la configuración de cultura del usuario actual. Ver mi respuesta a esta pregunta. – qbeuek

0

Como @Brian R. Bondy señaló que depende de la implementación de g [ 0] ["MyUntypedDateField"]. La práctica segura es usar DateTime.TryParse y como operador.

+0

Evitemos el código defensivo. El desarrollador debe saber qué tipo/formato esperar y ** falla ** (por ejemplo, arrojar una excepción) cuando el valor suministrado es de un formato o tipo diferente. TryParse se debe utilizar ** solo ** en la entrada proporcionada por el usuario. – qbeuek

+0

"Evitemos escribir código defensivo" lo escuché millones de veces. Por lo general, termina como "¡Maldición! ¡Cambiaron la implementación interna!" – aku

+0

@qbeuek ... ¿no se supone que es "indulgente con la entrada y estricto con la salida"? – DefenestrationDay

0

Parse requiere una cadena para la entrada, la conversión requiere un objeto, por lo que en el segundo ejemplo que proporcione arriba, se requiere realizar dos conversiones: una de un objeto a una cadena, luego de una cadena a DateTime. El primero no.

Sin embargo, si existe el riesgo de una excepción al realizar el reparto, entonces es posible que desee ir por la segunda ruta para poder probar y evitar una costosa excepción. De lo contrario, elija la ruta más eficiente y simplemente realice una conversión (desde el objeto hasta DateTime) en lugar de dos veces (desde el objeto hasta la cadena hasta DateTime).

3

La fundición es la solamente buena respuesta.

Debe tener en cuenta que los resultados de ToString y Parse no siempre son exactos; existen casos en los que no puede realizar una ida y vuelta segura entre esas dos funciones.

La documentación de ToString dice que usa la configuración actual de cultivo de hilos. La documentación de Parse dice, sino que también utiliza la configuración de la cultura de rosca actual (hasta ahora tan bueno - que están usando la misma cultura), pero hay una observación explícita, de que:

formateo está influenciada por las propiedades de la corriente El objeto DateTimeFormatInfo, que de forma predeterminada se deriva del elemento Regional y Opciones de idioma en el Panel de control. Una razón por la que el método Parse puede arrojar inesperadamente FormatException es si las propiedades actuales DateTimeFormatInfo.DateSeparator y DateTimeFormatInfo.TimeSeparator tienen el mismo valor.

Así que dependiendo de la configuración de los usuarios, el/Código Analizar ToString puede y va a fallar de forma inesperada ...

1

Su código sugiere que la variable puede ser una fecha o una cadena que se parece a una fecha . Fechas puede simplemente regresar con un elenco, pero las cadenas deben ser analizadas.El análisis viene con dos advertencias;

  1. si no está seguro de esta cadena se puede analizar, a continuación, utilizar DateTime.TryParse().

  2. Siempre incluya una referencia a la cultura que desea analizar. ToShortDateString() devuelve diferentes salidas en diferentes lugares. Seguramente querrá analizar utilizando la misma cultura. Sugiero esta función que trata con ambas situaciones;

    private DateTime ParseDateTime(object data) 
    { 
        if (data is DateTime) 
        { 
         // already a date-time. 
         return (DateTime)data; 
        } 
        else if (data is string) 
        { 
         // it's a local-format string. 
         string dateString = (string)data; 
         DateTime parseResult; 
         if (DateTime.TryParse(dateString, CultureInfo.CurrentCulture, 
               DateTimeStyles.AssumeLocal, out parseResult)) 
         { 
          return parseResult; 
         } 
         else 
         { 
          throw new ArgumentOutOfRangeException("data", 
               "could not parse this datetime:" + data); 
         } 
        } 
        else 
        { 
         // it's neither a DateTime or a string; that's a problem. 
         throw new ArgumentOutOfRangeException("data", 
               "could not understand data of this type"); 
        } 
    } 
    

A continuación, llame así;

ParseDateTime(g[0]["MyUntypedDateField").ToShortDateString(); 

Tenga en cuenta que los datos mal se produce una excepción, por lo que se desea capturar eso.

También; el operador 'como' no funciona con el tipo de datos DateTime, ya que esto solo funciona con tipos de referencia, y DateTime es un tipo de valor.