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

Foi útil?

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!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top