Em .NET, há alguma vantagem para um try / catch onde a captura apenas relança [duplicado]
Pergunta
Duplicate possíveis:
Por captura e Exceção rethrow em C #?
Às vezes, se deparar com C # código que se parece com isso:
try
{
// Some stuff
}
catch (Exception e)
{
throw e;
}
Eu entendo a sua possível fazer algo como registrar a mensagem de exceção e, em seguida, relançar-lo. Estou falando de um prendedor que só relança a exceção. Eu não vejo um ponto para isso. Eu tenho três perguntas:
1) Existe alguma vantagem para este
2) Será que esta doen lento o código em tudo
3) Faria alguma diferença se o bloco catch foram os seguintes:
catch (Exception)
{
throw;
}
Solução
Esta relança o exata ??em> mesma exceção:
catch (Exception)
{
throw;
}
Considerando que a presente relança a exceção sem o rastreamento de pilha original:
catch (Exception e)
{
throw e;
}
Muitas vezes há uma boa razão para throw;
como você pode registrar a exceção ou fazer outras coisas antes de rethrowing a exceção. Não tenho conhecimento de quaisquer boas razões para throw e;
como você vai acabar com as valiosas informações rastreamento de pilha.
Outras dicas
Não se você não fizer nada mais na captura ... Mas isso é muitas vezes usado para fazer outras coisas na captura, como a extração de madeira, ou outros tipos de procesing exceção, antes rethrowing-lo.
Eu uso essa técnica para que eu possa colocar um ponto de interrupção no lance quando a depuração. Às vezes eu removê-lo depois que eu sou feito ...
A principal diferença é que o rastreio da pilha de excepção será alterado para mostrar que se originou a partir do local da tentativa-captura no primeiro exemplo.
O segundo exemplo mantém o rastreamento de pilha.
Existe uma vantagem
Normalmente, não há falar. Todos este padrão vai fazer é redefinir o rastreamento de pilha, a ponto do novo lançamento. Isso só vai tornar mais difícil para os desenvolvedores a rastrear a origem do problema
Será que retardar o código em tudo
Em todos? Possivelmente. Retardá-lo por qualquer diferença mensurável? Não.
Faria alguma diferença se o bloco catch foram os seguintes?
Sim, essa captura é essencial e completamente redundante. Ele vai relançar a exceção que irá manter o rastreamento de pilha original e não têm impacto percievable em sua aplicação.
1 - Não vejo qualquer vantagem em tudo. Se você não está lidando com a exceção, deixar o try / catch off. O outro problema com este exemplo é que você não está jogando a exceção real, mas um novo.
2 - Sim. - mas a menos que isso está sentado em um grande laço de código repetido, você provavelmente não vai notar uma diferença
3 - Sim. No primeiro exemplo, você está brincando com a sua pilha de chamadas. Este exemplo mantém a pilha intacta por borbulhando a exceção, em vez de jogar um novo.
Se você está realmente fazendo nada mais, só há uma vantagem que eu já encontrados: você pode colocar um ponto de interrupção na linha throw
. Isso torna muito específico (ao invés de apenas quebrar sempre que esse tipo de exceção é lançada).
Eu só faria isso durante a depuração no entanto, em seguida, reverter a parte de trás de código.
Eu escrevi um teste rápido para mostrar as diferenças. Aqui está o código de teste:
try
{
var broken = int.Parse("null");
}
catch (Exception ex1)
{
System.Diagnostics.Trace.WriteLine(ex1.ToString());
}
try
{
try
{
var broken = int.Parse("null");
}
catch (Exception)
{
throw;
}
}
catch (Exception ex2)
{
System.Diagnostics.Trace.WriteLine(ex2.ToString());
}
try
{
try
{
var broken = int.Parse("null");
}
catch (Exception ex3)
{
throw ex3;
}
}
catch (Exception ex4)
{
System.Diagnostics.Trace.WriteLine(ex4.ToString());
}
A execução deste, eu recebo o seguinte resultado:
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.Int32.Parse(String s)
at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 18
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.Int32.Parse(String s)
at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 33
A first chance exception of type 'System.FormatException' occurred in mscorlib.dll
A first chance exception of type 'System.FormatException' occurred in QuickTests.exe
System.FormatException: Input string was not in a correct format.
at QuickTests.Program.Main(String[] args) in C:\Projects\Test\QuickTests\Program.cs:line 49
Você notará que as duas primeiras exceções são funcionam da mesma maneira. Assim, "jogar"; não muda nada, tanto quanto a ressalva de que se move para cima da pilha. No entanto "jogar ex3"; faz com que a exceção relatado para ser diferente, mudando o rastreamento de pilha da exceção.
Muitas vezes é bom para o registo. Além disso, se você deixar de fora o argumento na re-lançar, em seguida, ele não altera o rastreamento de pilha de e.
Às vezes você deseja permitir através de certos tipos exemplo aqui está um processamento especial para tudo, mas FooException:
try
{
// ...
}
catch (FooException)
{
throw;
}
catch (Exception ex)
{
// handle differently, like wrap with a FooException
throw new FooException("I pitty the Foo.", ex);
}
Claro.
Na maioria das vezes você quiser registrar a exceção antes de jogá-lo, e talvez gravar alguns valores variáveis ??do método.
Apenas captura-lo para jogá-lo, porém, não ganhar-lhe um monte.
Assim como essa, não. No entanto, você pode querer fazer isso:
catch (Exception ex)
{
LogException(ex);
throw;
}
Onde LogException () é uma classe personalizada que, erm, registra a exceção ou e-mails um alerta ou algo assim.
Eu acho que o ponto é para garantir que apenas um tipo de exceção é lançada. É um muito ruim IMHO anti-padrão
por exemplo.
try
{
throw XYZ();
}
catch(Exception e)
{
throw e;
}