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 lugar de Dictionary 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 a Convert.ToDouble(object) o Convert.ToDouble(string) ?

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 con 1,000 iteraciones y Convert.ToDouble con una mala entrada me llevó 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, la excepción de Convert.ToDouble arruinará su rendimiento.

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

Para empezar, usaría double.Parse lugar de Convert.ToDouble en primer lugar.

En cuanto a si debe usar Parse o TryParse : ¿puede continuar si hay datos de entrada incorrectos, o es realmente una condición excepcional? Si es excepcional, use Parse y déjelo explotar si la entrada es mala. Si se espera y se puede manejar limpiamente, use TryParse .

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 stack de excepción.

Generalmente trato de evitar la clase Convert (es decir, no la uso) porque la encuentro muy confusa: el código da muy pocas pistas sobre qué sucede exactamente aquí, ya que Convert permite que ocurran muchas conversiones semánticamente muy diferentes con el mismo código Esto hace que sea difícil controlar para el progtwigdor lo que está sucediendo exactamente.

Mi consejo, por lo tanto, es nunca usar esta clase. Tampoco es realmente necesario (excepto para el formato binario de un número, porque el método normal de ToString de las clases numéricas no ofrece un método apropiado para hacerlo).

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.

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) lo hará ((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); 

Por lo tanto, es más rápido hacer el double.Parse . double.Parse directamente.

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 hacer que la cadena sea analizada primero y, dependiendo de su entrada, puede ser más costosa.

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).

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

Personalmente, encuentro que el método TryParse es más fácil de leer, el que realmente querrás usar depende de tu caso de uso: si los errores se pueden manejar localmente, estás esperando errores y un bool de TryParse es bueno, de lo contrario es posible que desees solo deja volar las excepciones.

Esperaría que el TryParse sea ​​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.