Se um bloco finalmente lança uma exceção, o que exatamente acontece?
Especificamente, o que acontece se a exceção for lançada no meio de um bloco finalmente. O restante das instruções (depois) deste bloco é invocado?
Estou ciente de que as exceções se propagarão para cima.
c#
exception
exception-handling
try-catch-finally
Jack Kada
fonte
fonte
Respostas:
Essa exceção se propaga para fora e para cima e será (pode) tratada em um nível superior.
Seu bloqueio final não será concluído além do ponto em que a exceção é lançada.
Se o bloco finalmente estiver sendo executado durante o tratamento de uma exceção anterior, essa primeira exceção será perdida.
fonte
ThreadAbortException
, então todo o bloco final será finalizado primeiro, pois é uma seção crítica.Para perguntas como essas, geralmente abro um projeto de aplicativo de console vazio no Visual Studio e escrevo um pequeno programa de exemplo:
Quando você executa o programa, verá a ordem exata na qual os blocos
catch
efinally
são executados. Observe que o código no bloco final após o lançamento da exceção não será executado (de fato, neste programa de exemplo, o Visual Studio até avisará que ele detectou código inacessível):Observação adicional
Como Michael Damatov apontou, uma exceção do
try
bloco será "comida" se você não lidar com isso em umcatch
bloco (interno) . De fato, no exemplo acima, a exceção lançada novamente não aparece no bloco de captura externo. Para tornar isso ainda mais claro, observe a seguinte amostra ligeiramente modificada:Como você pode ver na saída, a exceção interna é "perdida" (ou seja, ignorada):
fonte
finally
bloco (quase) sempre será executado; isso também vale para o bloco final interno (tente o programa de amostra você mesmo (um bloco finalmente não será executado no caso de um não recuperável) exceção, por exemplo, umEngineExecutionException
, mas nesse caso a seu programa terminará imediatamente de qualquer maneira).Se houver uma exceção pendente (quando o
try
bloco tiver umfinally
mas nãocatch
), a nova exceção substituirá essa.Se não houver exceção pendente, ele funciona da mesma maneira que lança uma exceção fora do
finally
bloco.fonte
catch
bloco que (re) lança uma exceção.A exceção é propagada.
fonte
Snippet rápido (e bastante óbvio) para salvar a "exceção original" (lançada em
try
bloco) e sacrificar a "finalmente exceção" (lançada emfinally
bloco), caso o original seja mais importante para você:Quando o código acima é executado, "Exceção original" propaga a pilha de chamadas e "Finalmente exceção" é perdida.
fonte
Eu tive que fazer isso para detectar um erro ao tentar fechar um fluxo que nunca foi aberto devido a uma exceção.
se o webRequest foi criado, mas ocorreu um erro de conexão durante o
o finalmente capturaria uma exceção ao tentar fechar as conexões que julgava abertas porque o webRequest havia sido criado.
Se o finalmente não tivesse um try-catch dentro, esse código causaria uma exceção não tratada durante a limpeza do webRequest
a partir daí, o código sairia sem manipular adequadamente o erro que ocorreu e, portanto, causar problemas no método de chamada.
Espero que isso ajude como um exemplo
fonte
Lançar uma exceção enquanto outra exceção estiver ativa resultará na substituição da primeira exceção pela segunda exceção (posterior).
Aqui está um código que ilustra o que acontece:
fonte
Há alguns meses, eu também enfrentei algo assim,
Para resolver esse problema, criei uma classe de utilidade como
E usado assim
mas se você quiser usar paramaters e retornar tipos, é outra história
fonte
A maneira como as exceções lançadas pelo CodeA e CodeB são tratadas é a mesma.
Uma exceção lançada em um
finally
bloco não tem nada de especial; trate-a como a exceção lançada pelo código B.fonte
A exceção se propaga e deve ser tratada em um nível superior. Se a exceção não for tratada no nível superior, o aplicativo trava. A execução do bloco "finalmente" para no ponto em que a exceção é lançada.
Independentemente de haver uma exceção ou não, o bloco "finalmente" é garantido para execução.
Se o bloco "final" estiver sendo executado após uma exceção no bloco try,
e se essa exceção não for tratada
e se o bloco finalmente lança uma exceção
Em seguida, a exceção original que ocorreu no bloco try é perdida.
Ótimo artigo para detalhes
fonte
Ele lança uma exceção;) Você pode capturar essa exceção em alguma outra cláusula catch.
fonte