Pregunta Double.TryParse o Convert.ToDouble - ¿Qué es más rápido y más seguro?


Mi aplicación lee un archivo Excel usando VSTO y agrega los datos leídos a un StringDictionary. Agrega solo datos que son números con algunos dígitos (1000 1000,2 1000,34 - la coma es un delimitador en los estándares rusos).

¿Qué es mejor verificar si la cadena actual es un número apropiado?

object data, string key; // data had read

try
{
  Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
  dic.Add(key, regionData.ToString());
}
catch (InvalidCastException)
{
  // is not a number
}

o

double d;
string str = data.ToString();
if (Double.TryParse(str, out d)) // if done, then is a number
{
  dic.Add(key, str);
}

Tengo que usar StringDictionary en lugar de Dictionary<string, double> debido a los siguientes problemas del algoritmo de análisis.

Mis preguntas: ¿Qué camino es más rápido? ¿Cuál es más seguro?

Y es mejor llamar Convert.ToDouble(object) o Convert.ToDouble(string) ?


74
2018-02-25 15:23


origen


Respuestas:


Hice una prueba rápida no científica en el modo de lanzamiento. Usé dos entradas: "2.34523" y "badinput" en ambos métodos e iteración 1,000,000 de veces.

Entrada válida:

Double.TryParse = 646ms
Convert.ToDouble = 662 ms

No es muy diferente, como se esperaba. Para todos los efectos, para una entrada válida, estos son los mismos.

Entrada inválida:

Double.TryParse = 612ms
Convert.ToDouble = ..

Bueno ... estuvo funcionando durante mucho tiempo. Volví a usar todo el proceso usando 1,000 iteraciones y Convert.ToDouble con mala entrada tomó 8.3 segundos. Promediando, tomaría más de 2 horas. No me importa qué tan básica es la prueba, en el caso de entrada no válida, Convert.ToDoubleEl aumento de excepciones arruinará tu rendimiento.

Entonces, aquí hay otra votación para TryParse con algunos números para respaldarlo.


126
2018-02-25 15:44



Para empezar, usaría double.Parse más bien que Convert.ToDouble en primer lugar.

En cuanto a si deberías usar Parse o TryParse: ¿puedes continuar si hay datos de entrada incorrectos, o es una condición realmente excepcional? Si es excepcional, usa Parse y deja que explote si la entrada es mala. Si se espera y puede manejarse limpiamente, use TryParse.


43
2018-02-25 15:29



Si no va a manejar la excepción, vaya con TryParse. TryParse es más rápido porque no tiene que ocuparse de todo el trazado de la pila de excepción.


7
2018-02-25 15:26



Generalmente trato de evitar el Convert clase (es decir: no lo uso) porque me resulta muy confuso: el código da muy pocas pistas sobre lo que sucede exactamente aquí desde Convert permite que ocurran muchas conversiones semánticamente muy diferentes con el mismo código. Esto hace que sea difícil controlar para el programador lo que está sucediendo exactamente.

Mi consejo, por lo tanto, es nunca usar esta clase. Tampoco es realmente necesario (a excepción del formato binario de un número, porque lo normal ToString método de clases de números no ofrece un método apropiado para hacer esto).


7
2018-02-25 15:27



A menos que esté 100% seguro de sus entradas, lo que rara vez es el caso, debe usar Double.TryParse.

Convert.ToDouble will throw an exception on non-numbers
Double.Parse will throw an exception on non-numbers or null
Double.TryParse will return false or 0 on any of the above without generating an exception.

La velocidad del análisis se vuelve secundaria cuando lanza una excepción porque no hay mucho más lento que una excepción.


7
2017-12-19 15:11



Las directrices de diseño de .NET Framework recomiendan utilizar los métodos de prueba. Evitar excepciones suele ser una buena idea.

Convert.ToDouble(object) va a hacer ((IConvertible) object).ToDouble(null);

Que llamará Convert.ToDouble(string, null)

Entonces, es más rápido llamar a la versión de cadena.

Sin embargo, la versión de cadena simplemente hace esto:

if (value == null)
{
    return 0.0;
}
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);

Entonces es más rápido hacer double.Parse directamente.


7
2018-02-25 15:26



Aquí hay mucho odio por la clase Convert ... Solo para equilibrar un poco, hay una ventaja para Convert: si le entregan un objeto,

Convert.ToDouble(o);

puede simplemente devolver el valor fácilmente si o ya es un Double (o un int o cualquier elemento que se pueda convertir fácilmente).

Usar Double.Parse o Double.TryParse es genial si ya lo tienes en una cadena, pero

Double.Parse(o.ToString());

tiene que ir hacer la cadena a ser analizada primero y dependiendo de su entrada que podría ser más costosa.


3
2017-09-14 20:49



Double.TryParse IMO.

Es más fácil de manejar, sabrá exactamente dónde ocurrió el error.

Entonces puede manejarlo como le parezca mejor si devuelve falso (es decir, no se pudo convertir).


2
2018-02-25 15:26



Siempre he preferido usar el TryParse() métodos porque va a escupir el éxito o la falla al convertir sin tener que preocuparse por las excepciones.


2
2018-02-25 15:28



Personalmente, encuentro el TryParse método más fácil de leer, cuál de todos modos querrá usar depende de su caso de uso: si los errores se pueden manejar localmente, está esperando errores y un bool de TryParse es bueno, de lo contrario es posible que desee dejar volar las excepciones.

Yo esperaría que TryParse para ser más rápido también, ya que evita la sobrecarga del manejo de excepciones. Pero use una herramienta de referencia, como MiniBench de Jon Skeet para comparar las diversas posibilidades.


1
2018-02-25 15:29