Falando francamente, eu já fui um programador 100% de VB, e confesso que paguei meus estudos universitários com ASP, VB6 e VB.NET.
Durante meu amadurecimento profissional conheci o C#.NET e uma das coisas que mais me incomodaram foi o fato do C# não possuir a diretiva (On Error Resume Next).
Na minha humilde opinião o (On Error Resume Next) é uma diretiva de emergência em casos de problemas indesejados.
O que isso faz?
Para responder a esta pergunta, temos de pensar em situações críticas.
Vamos usar um pouco de imaginação e pensar em um login de usuários de uma loja de e-commerce.
O login vai funcionando muito bem até que um dia temos a indesejada tela de erro quando qualquer usuário tenta realizar o login.
Então, temos duas possíveis vertentes de ação:
- Parar e entender o erro, corrigir o problema e alterar em produção.
- Dar um jeito.
Mesmo eu admito que, por mais que a 1º opção seja absolutamente correta, em situações tão críticas quando essas (e elas existem sim!) nós torcemos para que um (On Error Resume Next) funcione.
Então, a primeira coisa que fazemos é tentar usar. Se funcionar é lucro e o problema está resolvido :-)
Porque não usar?
Além do obvio motivo de que usar uma declarativa destas é admitir que não sabemos programar corretamente e/ou admitir que não conseguimos achar o erro em nossa aplicação, existe a questão da performance.
SIM!!!!!!!!!!!!!!!!!!!!!
Você está lendo certo. Quando usamos o (On Error Resume Next) em uma aplicação VB.NET, mesmo que o código esteja 1000% correto, teremos um GRANDE problema de performance e vou provar isso abaixo.
Como forma de exemplo, utilizaremos uma função de demonstração com vários pontos de erro possíveis, principalmente dentro de um loop:
Function ContaCaracteresNumericos(ByVal entrada As String) As Integer
' Cria as Variaveis
Dim qtdCaracteres As Integer = 0
Dim entradaChar As Char()
' Quebra a Entrada em Caracteres
entradaChar = entrada.ToCharArray()
' Looping nos Elementos para Verificar se TODOS são Numeros
For i As Integer = 0 To entradaChar.Length - 1
' Converte para Numero
Dim tmpNumero As Integer = entradaChar(i).ToString()
' Verifica se é Maior que Zero
If (tmpNumero > 0) Then
' Soma no Contador
qtdCaracteres = qtdCaracteres + 1
End If
Next
' Retorna Total
Return qtdCaracteres
End Function
Na outra ponta, precisamos analisar o código que o compilador do VB.NET gera, então para isso usaremos o sempre útil Reflector.
Public Shared Function ContaCaracteresNumericos(ByVal entrada As String) As Integer
Dim entradaChar As Char() = entrada.ToCharArray
Dim VB$t_i4$L0 As Integer = (entradaChar.Length - 1)
Dim i As Integer = 0
Do While (i <= VB$t_i4$L0)
If (Conversions.ToInteger(entradaChar(i).ToString) > 0) Then
qtdCaracteres += 1
End If
i += 1
Loop
Return qtdCaracteres
End Function
Podemos observar que não há nada de incomum além das otimizações naturais que esperamos de um compilador Microsoft.
Até agora sem segredos, então, passemos a utilizar o (On Error Resume Next):
Function ContaCaracteresNumericos(ByVal entrada As String) As Integer
' Set Performance = Ruim
On Error Resume Next
' Cria as Variaveis
Dim qtdCaracteres As Integer = 0
Dim entradaChar As Char()
' Quebra a Entrada em Caracteres
entradaChar = entrada.ToCharArray()
' Looping nos Elementos para Verificar se TODOS são Numeros
For i As Integer = 0 To entradaChar.Length - 1
' Converte para Numero
Dim tmpNumero As Integer = entradaChar(i).ToString()
' Verifica se é Maior que Zero
If (tmpNumero > 0) Then
' Soma no Contador
qtdCaracteres = qtdCaracteres + 1
End If
Next
' Retorna Total
Return qtdCaracteres
End Function
E o código gerado?
Public Shared Function ContaCaracteresNumericos(ByVal entrada As String) As Integer
Dim VB$ResumeTarget As Integer
Try
Dim VB$CurrentStatement As Integer
Label_0001:
ProjectData.ClearProjectError
Dim VB$ActiveHandler As Integer = -2
Label_000A:
VB$CurrentStatement = 2
Dim qtdCaracteres As Integer = 0
Label_000F:
VB$CurrentStatement = 3
Dim entradaChar As Char() = entrada.ToCharArray
Label_0019:
VB$CurrentStatement = 4
Dim VB$t_i4$L0 As Integer = (entradaChar.Length - 1)
Dim i As Integer = 0
goto Label_005C
Label_0027:
VB$CurrentStatement = 5
Dim tmpNumero As Integer = Conversions.ToInteger(entradaChar(i).ToString)
Label_003D:
VB$CurrentStatement = 6
If (tmpNumero <= 0) Then
goto Label_0053
End If
Label_004B:
VB$CurrentStatement = 7
qtdCaracteres += 1
Label_0053:
VB$CurrentStatement = 9
i += 1
Label_005C:
If (i <= VB$t_i4$L0) Then
goto Label_0027
End If
Label_0065:
VB$CurrentStatement = 10
ContaCaracteresNumericos = qtdCaracteres
goto Label_0102
Label_0079:
VB$ResumeTarget = 0
Select Case (VB$ResumeTarget + 1)
Case 1
goto Label_0001
Case 2
goto Label_000A
Case 3
goto Label_000F
Case 4
goto Label_0019
Case 5
goto Label_0027
Case 6
goto Label_003D
Case 7
goto Label_004B
Case 8, 9
goto Label_0053
Case 10
goto Label_0065
Case 11
goto Label_0102
Case Else
goto Label_00F7
End Select
Label_00B7:
VB$ResumeTarget = VB$CurrentStatement
Select Case IIf((VB$ActiveHandler > -2), VB$ActiveHandler, 1)
Case 0
goto Label_00F7
Case 1
goto Label_0079
End Select
Catch obj1 As Object When (?)
ProjectData.SetProjectError(DirectCast(obj1, Exception))
goto Label_00B7
End Try
Label_00F7:
Throw ProjectData.CreateProjectError(-2146828237)
Label_0102:
If (VB$ResumeTarget <> 0) Then
ProjectData.ClearProjectError
End If
Return ContaCaracteresNumericos
End Function
Analisando o código gerado com um pouco mais de atenção, podemos observar que, além da quantidade de linhas de código ter aumentado consideravelmente (o que é obvio), o loop desapareceu e foi trocado por instruções GOTO e todas as linhas de código ganharam overhead de código (outras linhas).
Aqueles que desejam ter o deleite de analisar o resultado com C#, segue o código abaixo:
public static int ContaCaracteresNumericos(string entrada)
{
int ContaCaracteresNumericos;
int VB$ResumeTarget;
try
{
int VB$CurrentStatement;
Label_0001:
ProjectData.ClearProjectError();
int VB$ActiveHandler = -2;
Label_000A:
VB$CurrentStatement = 2;
int qtdCaracteres = 0;
Label_000F:
VB$CurrentStatement = 3;
char[] entradaChar = entrada.ToCharArray();
Label_0019:
VB$CurrentStatement = 4;
int VB$t_i4$L0 = entradaChar.Length - 1;
int i = 0;
goto Label_005C;
Label_0027:
VB$CurrentStatement = 5;
int tmpNumero = Conversions.ToInteger(entradaChar[i].ToString());
Label_003D:
VB$CurrentStatement = 6;
if (tmpNumero <= 0)
{
goto Label_0053;
}
Label_004B:
VB$CurrentStatement = 7;
qtdCaracteres++;
Label_0053:
VB$CurrentStatement = 9;
i++;
Label_005C:
if (i <= VB$t_i4$L0)
{
goto Label_0027;
}
Label_0065:
VB$CurrentStatement = 10;
ContaCaracteresNumericos = qtdCaracteres;
goto Label_0102;
Label_0079:
VB$ResumeTarget = 0;
switch ((VB$ResumeTarget + 1))
{
case 1:
goto Label_0001;
case 2:
goto Label_000A;
case 3:
goto Label_000F;
case 4:
goto Label_0019;
case 5:
goto Label_0027;
case 6:
goto Label_003D;
case 7:
goto Label_004B;
case 8:
case 9:
goto Label_0053;
case 10:
goto Label_0065;
case 11:
goto Label_0102;
default:
goto Label_00F7;
}
Label_00B7:
VB$ResumeTarget = VB$CurrentStatement;
switch (((VB$ActiveHandler > -2) ? VB$ActiveHandler : 1))
{
case 0:
goto Label_00F7;
case 1:
goto Label_0079;
}
}
catch (object obj1) when (?)
{
ProjectData.SetProjectError((Exception) obj1);
goto Label_00B7;
}
Label_00F7:
throw ProjectData.CreateProjectError(-2146828237);
Label_0102:
if (VB$ResumeTarget != 0)
{
ProjectData.ClearProjectError();
}
return ContaCaracteresNumericos;
}
A que conclusão chegamos?
Vou encerrando o artigo por aqui e fica uma reflexão:
“Vale a pena tudo isso pela comodidade do código continuar a executar mesmo dando erro?”
Posts Relacionados:



Be the first to start a conversation