Maneira mais eficiente de testar o tipo de objeto
Pergunta
Eu tenho valores armazenados como strings em um DataTable
onde cada valor poderia realmente representar um int
, double
, ou string
(todos foram convertidos em strings durante um processo de importação de uma fonte de dados externa).Preciso testar e ver que tipo realmente é cada valor.
O que é mais eficiente para a aplicação (ou não há diferença prática)?
- Tente converter para
int
(e entãodouble
).Se a conversão funcionar, o retornotrue
.Se uma exceção for lançada, retornefalse
. - Expressões regulares projetadas para corresponder ao padrão de um
int
oudouble
- Algum outro método?
Solução
Usaria double.TryParse, tem benefícios de desempenho.
Outras dicas
Eu diria, não se preocupe tanto com esse microdesempenho.É muito melhor apenas fazer algo funcionar e torná-lo o mais claro, conciso e fácil de ler possível.A pior coisa que você pode fazer é sacrificar a legibilidade por uma quantidade insignificante de desempenho.
No final, a melhor maneira de lidar com problemas de desempenho é salvá-los para quando você tiver dados que indiquem que há um problema real de desempenho...caso contrário, você gastará muito tempo micro-otimizando e, na verdade, causará custos de manutenção mais elevados no futuro.
Se você achar que essa situação de análise é realmente o gargalo em seu aplicativo, ENTÃO é a hora de tentar descobrir qual é a maneira mais rápida de resolver o problema.Acho que Jeff (e muitos outros) têm blogado muito sobre esse tipo de coisa.
Você obterá resultados diferentes para os diferentes métodos, dependendo se você compila com otimizações ativadas.Você basicamente tem algumas opções:
object o;
//checking with is
o is int
//check type
o.GetType() != typeof( int )
//cast and catch exception
try{ int j = (int) o; }
catch {}
//use the tryparse
int.TryParse( Convert.ToString( o ), out j )
Você pode configurar facilmente um aplicativo de console que tente cada uma dessas 10.000 vezes e retorne a duração de cada uma (teste quando o for um int e quando for outra coisa).
O try-catch
método é o mais rápido se o objeto contiver um int, e de longe o mais lento se não contiver (ainda mais lento que GetType
). int.TryParse
é muito rápido se você tiver uma string, mas se você tiver um objeto desconhecido, será mais lento.
Curiosamente, com o .Net 3.5 e as otimizações ativadas, o o is int
a verificação leva o mesmo tempo que try-catch
quando o na verdade é um int. o is int
é apenas um pouco mais lento se o realmente for outra coisa.
Irritantemente, o FxCop emitirá avisos se você fizer algo como:
if( o is int )
int j = (int) o;
Mas acho que isso é um bug no FxCop - ele não sabe que int é um tipo de valor e recomenda que você use o as int
em vez de.
Se sua entrada for sempre uma string int.TryParse
é o melhor, caso contrário o is
operador é o mais rápido.
Como você tem uma string, eu verifico se você precisa saber que é um int, em vez de um double.Se int.TryParse
passa então o mesmo acontecerá double.TryParse
então você pode metade do número de verificações - retornar double ou string e diminuir as duplas quando espera um int.
O problema que você tem é que pode haver situações em que a resposta pode ser todos os três tipos.
3 pode ser um int, um double ou uma string!
Depende do que você está tentando fazer e da importância de eles serem de um tipo específico.Talvez seja melhor deixá-los como estão o maior tempo possível ou, alternativamente, criar um método para marcar cada um deles (se você tiver controle da origem da string original).
Eu pessoalmente usaria int.tryparse e depois double.tryparse.O desempenho nesses métodos é bastante rápido.Ambos retornam um booleano.Se ambos falharem, você terá uma string, de acordo com a forma como definiu seus dados.