Mi aplicación lee un archivo de Excel usando VSTO y agrega los datos leídos a un archivo StringDictionary
. Agrega solo datos que son números con unos pocos dígitos (1000 1000,2 1000,34 - la coma es un delimitador en los estándares rusos).
¿Qué es mejor para 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 usarlo en StringDictionary
lugar de Dictionary<string, double>
debido a los siguientes problemas de algoritmo de análisis.
Mis preguntas: ¿Qué camino es más rápido? ¿Qué es más seguro?
¿Y es mejor llamar Convert.ToDouble(object)
o Convert.ToDouble(string)
?
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 iteraron 1,000,000 veces.
Entrada válida:
Double.TryParse = 646ms Convert.ToDouble = 662 ms
No 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. Repetí todo usando 1,000 iteraciones y
Convert.ToDouble
con una mala entrada tardé 8.3 segundos. Haciendo un promedio, tomaría más de 2 horas. No me importa cuán básica sea la prueba, en el caso de entrada no válida,Convert.ToDouble
la activación de excepciones arruinará su rendimiento.Entonces, aquí hay otro voto a favor
TryParse
con algunos números para respaldarlo.fuente
Para empezar, usaría en
double.Parse
lugar deConvert.ToDouble
en primer lugar.En cuanto a si debe usar
Parse
oTryParse
: ¿puede continuar si hay datos de entrada incorrectos o es una condición realmente excepcional? Si es excepcional, utilíceloParse
y déjelo explotar si la entrada es mala. Si se espera y se puede manipular limpiamente, úseloTryParse
.fuente
Las pautas de diseño de .NET Framework recomiendan utilizar los métodos Try. Evitar excepciones suele ser una buena idea.
Convert.ToDouble(object)
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);
Así que es más rápido hacerlo
double.Parse
directamente.fuente
Si no va a manejar la excepción, vaya con TryParse. TryParse es más rápido porque no tiene que lidiar con todo el seguimiento de la pila de excepciones.
fuente
Generalmente trato de evitar la
Convert
clase (es decir, no la uso) porque la encuentro muy confusa: el código da muy pocas pistas sobre lo que sucede exactamente aquí desdeConvert
permite que ocurran muchas conversiones semánticamente muy diferentes con el mismo código . Esto dificulta que el programador controle qué está sucediendo exactamente.Mi consejo, por lo tanto, es que nunca uses esta clase. Tampoco es realmente necesario (excepto para el formato binario de un número, porque el
ToString
método normal de clases de números no ofrece un método apropiado para hacer esto).fuente
A menos que esté 100% seguro de sus entradas, 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 es mucho más lenta que una excepción.
fuente
Hay mucho odio por la clase Convert aquí ... Solo para equilibrar un poco, hay una ventaja para Convert: si te entregan un objeto,
puede devolver el valor fácilmente si o ya es un Double (o un int o cualquier cosa que se pueda lanzar fácilmente).
Usar Double.Parse o Double.TryParse es genial si ya lo tiene en una cadena, pero
primero tiene que hacer que la cadena se analice y, dependiendo de su entrada, eso podría ser más costoso.
fuente
Convert.ToSomething()
es mucho más caro que Parse / TryParse, especialmente en un contexto de iteraciónDouble. TryParse IMO.
Es más fácil de manejar para usted, sabrá exactamente dónde ocurrió el error.
Luego, puede manejarlo como mejor le parezca si devuelve falso (es decir, no se pudo convertir).
fuente
Siempre he preferido usar los
TryParse()
métodos porque va a devolver el éxito o el fracaso en la conversión sin tener que preocuparme por las excepciones.fuente
Ésta es una vieja pregunta interesante. Estoy agregando una respuesta porque nadie notó un par de cosas con la pregunta original.
¿Qué es más rápido: Convert.ToDouble o Double.TryParse? ¿Qué es más seguro: Convert.ToDouble o Double.TryParse?
Voy a responder estas dos preguntas (actualizaré la respuesta más adelante), en detalle, pero primero:
Por seguridad, lo que todos los programadores se perdieron en esta pregunta es la línea (énfasis mío):
Seguido por este ejemplo de código:
Lo interesante aquí es que si las hojas de cálculo están en formato numérico ruso pero Excel no ha escrito correctamente los campos de celda, ¿cuál es la interpretación correcta de los valores provenientes de Excel?
Aquí hay otra cosa interesante sobre los dos ejemplos, con respecto a la velocidad:
catch (InvalidCastException) { // is not a number }
Es probable que esto genere un MSIL con este aspecto:
catch [mscorlib]System.InvalidCastException { IL_0023: stloc.0 IL_0024: nop IL_0025: ldloc.0 IL_0026: nop IL_002b: nop IL_002c: nop IL_002d: leave.s IL_002f } // end handler IL_002f: nop IL_0030: return
En este sentido, probablemente podamos comparar el número total de instrucciones MSIL llevadas a cabo por cada programa, más sobre eso más adelante cuando actualice esta publicación.
Creo que el código debe ser correcto, claro y rápido ... ¡ en ese orden!
fuente
Personalmente, encuentro que el
TryParse
método es más fácil de leer, el que realmente querrá usar depende de su caso de uso: si los errores se pueden manejar localmente, está esperando errores y un bool deTryParse
es bueno, de lo contrario, es posible que desee dejar las excepciones vuelan.Esperaría
TryParse
que también fuera más rápido, 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.fuente