Double.TryParse ou Convert.ToDouble - que é mais rápido e mais seguro?
Pergunta
Meu aplicativo lê um arquivo do Excel usando VSTO e adiciona os dados lidos a um StringDictionary
. Acrescenta apenas dados que são números com alguns dígitos (1000 1000,2 1000,34 - vírgula é um delimitador em padrões russos).
O que é melhor para verificar se a cadeia atual é um número apropriado?
object data, string key; // data had read
try
{
Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
dic.Add(key, regionData.ToString());
}
catch (InvalidCastException)
{
// is not a number
}
ou
double d;
string str = data.ToString();
if (Double.TryParse(str, out d)) // if done, then is a number
{
dic.Add(key, str);
}
Eu tenho que usar StringDictionary
vez de Dictionary<string, double>
por causa das questões seguinte algoritmo de análise.
As minhas perguntas: Qual o caminho é mais rápido? Que é mais seguro?
E é melhor Convert.ToDouble(object)
chamada ou Convert.ToDouble(string)
?
Solução
Eu fiz um teste não-científica rápida no modo de versão. Eu usei duas entradas:. "2,34523" e "badinput" em ambos os métodos e reiterou 1.000.000 vezes
A entrada válida:
Double.TryParse = 646ms
Convert.ToDouble = 662 ms
Não muito diferente, como esperado. Para todos os efeitos, para a entrada válida, estes são os mesmos.
Entrada inválida:
Double.TryParse = 612ms
Convert.ToDouble = ..
Bem .. ele estava correndo por um longo tempo. I reran a coisa toda usando 1.000 iterações e Convert.ToDouble
com entrada mau levou 8,3 segundos. Média-lo para fora, levaria mais de 2 horas. Eu não me importo como básico o teste é, no caso de entrada inválido, angariação de exceção de Convert.ToDouble
vai arruinar a sua performance.
Então, aqui vai outra votação para TryParse
com alguns números para apoiá-la.
Outras dicas
Para começar, eu usaria double.Parse
em vez de Convert.ToDouble
em primeiro lugar.
Quanto a saber se você deve usar Parse
ou TryParse
: você pode avançar se há dados de entrada ruins, ou isso é uma condição realmente excepcional? Se é excepcional, o uso Parse
e deixá-lo explodir se a entrada é ruim. Se é esperado e pode ser limpa tratada, uso TryParse
.
diretrizes de design .NET Framework recomendo usar os métodos tentar. Evitando exceções é geralmente uma boa idéia.
Convert.ToDouble(object)
fará ((IConvertible) object).ToDouble(null);
O que vai chamar Convert.ToDouble(string, null)
Por isso, é mais rápido para chamar a versão string.
No entanto, a versão corda apenas faz isso:
if (value == null)
{
return 0.0;
}
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
Por isso, é mais rápido para fazer o double.Parse
diretamente.
Se você não está indo para ser manipulação movimento exceção com TryParse. TryParse é mais rápido porque ele não tem que lidar com todo o rastreamento de pilha de exceção.
Eu geralmente tentam evitar a classe Convert
(que significa: eu não usá-lo) porque acho que é muito confuso: o código dá também algumas sugestões sobre o que exatamente acontece aqui desde Convert
permite um monte de semanticamente muito diferentes conversões para ocorrer com o mesmo código. Isso torna mais difícil de controlar para o programador que exatamente está acontecendo.
O meu conselho é, portanto, nunca usar essa classe. Não é realmente necessário ou (exceto para formatação binária de um número, porque o método ToString
normal das aulas número não oferece um método apropriado para fazer isso).
A menos que você estiver 100% certo de suas entradas, o que raramente é o caso, você deve 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.
A velocidade da análise torna-se secundário quando você lançar uma exceção, porque não há muito mais lento do que uma exceção.
Lotes de ódio para a classe Convert aqui ... Apenas para equilibrar um pouco, há uma vantagem para converter - se você entregou um objeto,
Convert.ToDouble(o);
pode simplesmente devolver o valor com facilidade se o é já um duplo (ou um int ou qualquer coisa prontamente refratário).
Usando Double.Parse ou Double.TryParse é ótimo se você já tê-lo em uma corda, mas
Double.Parse(o.ToString());
tem que ir make a string a ser analisado em primeiro lugar e, dependendo da sua entrada que poderia ser mais caro.
Double.TryParse IMO.
É mais fácil para você lidar, Você saberá exatamente onde ocorreu o erro.
Depois, você pode lidar com isso como você vê o ajuste, se ele retorna falso (isto é, não poderia converter).
Eu sempre preferi usar os métodos TryParse()
porque ele está indo para o sucesso cuspir de volta ou o fracasso para converter sem ter que se preocupar com exceções.
Pessoalmente, acho que o método TryParse
mais fácil de ler, qual deles você realmente quiser usar depende do seu caso de uso: se erros podem ser tratados localmente você são erros que esperam e um bool de TryParse
é bom, então você pode querer apenas deixar as exceções voar.
Espero que o TryParse
para ser mais rápido também, uma vez que evita a sobrecarga de manipulação de exceção. Mas usar uma ferramenta de referência, como MiniBench de Jon Skeet para comparar as várias possibilidades.
Esta é uma velha questão interessante. Eu estou adicionando uma resposta porque ninguém notou um par de coisas com a pergunta original.
O que é mais rápido: Convert.ToDouble ou Double.TryParse? Que é mais seguro:? Convert.ToDouble ou Double.TryParse
Eu vou responder a estas duas perguntas (eu vou atualizar a resposta mais tarde), em detalhes, mas primeiro:
Por razões de segurança, a coisa todas programador perdeu nesta questão é a linha (grifo meu):
Ele adiciona somente os dados que são números com alguns dígitos (1000 1000,2 1000,34 - vírgula é um delimitador em padrões russos ).
Seguido por este exemplo de código:
Convert.ToDouble(regionData, CultureInfo.CurrentCulture);
O que é interessante aqui é que se as planilhas estão em formato de número russo, mas o Excel não tem digitados corretamente os campos celulares, o que é a interpretação correta dos valores vindos de Excel?
Aqui está outra coisa interessante sobre os dois exemplos, a respeito de velocidade:
catch (InvalidCastException)
{
// is not a number
}
Este é provavelmente vai gerar MSIL que se parece com isso:
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
Neste sentido, podemos provavelmente comparar o número total de instruções MSIL realizadas por cada programa -. Mais sobre isso depois que eu atualizar este post
Eu acredito que o código deve ser corretas, claras, e rápido ... Em que ordem!