try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
No bloco acima, quando o bloco finalmente é chamado? Antes do lançamento de e ou é finalmente chamado e depois capturado?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
No bloco acima, quando o bloco finalmente é chamado? Antes do lançamento de e ou é finalmente chamado e depois capturado?
Respostas:
Seria chamado depois que e for jogado novamente (ou seja, depois que o bloco catch for executado)
editando isso 7 anos depois - uma observação importante é que, se enão for capturado por um bloco try / catch mais adiante na pilha de chamadas ou tratado por um manipulador de exceção global, o finallybloco poderá nunca ser executado.
finallynão é executado se a exceção lançada no anterior catchnunca é pego em uma externa try- catchbloco!
Por que não tentar:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
com código (formatado para espaço vertical):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
outer try inner try inner catch Unhandled Exception: System.DivideByZeroException...
Depois de ler todas as respostas aqui, parece que a resposta final é que depende :
Se você repetir uma exceção dentro do bloco catch, e essa exceção for capturada dentro de outro bloco catch, tudo será executado de acordo com a documentação.
No entanto, se a exceção retrocedida não for tratada, ela finalmente nunca será executada.
Testei este exemplo de código no VS2010 com C # 4.0
static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
Aqui está a saída:
Exemplo 1: lance novamente dentro de outro bloco de tentativa:
--outer try
---- try
interior
---- catch interno ---- inner finalmente
--outer catch
--outer finalmente
Huzzah!Exemplo 2: lance novamente fora de outro bloco de tentativa:
--try
--catchExceção sem tratamento: System.Exception: exceção do tipo 'System.Exception' foi lançada.
em ConsoleApplication1.Program.Main () em C: \ source local \ ConsoleApplication1 \ Program.cs: linha 53
Seu exemplo se comportaria de forma idêntica a este código:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
Como uma observação lateral, se você realmente quer dizer throw e;(ou seja, lançar a mesma exceção que capturou), é muito melhor fazer isso throw;, pois isso preservará o rastreamento da pilha original em vez de criar um novo.
finallybloco será executado após o catchbloco (mesmo que o bloco catch repita a exceção), que é o que meu snippet está tentando ilustrar.
trybloco, minha resposta tem um "try-catch". Estou tentando explicar o comportamento da construção em três partes usando duas construções em duas partes. Não vejo nenhum sinal de um segundo trybloco na pergunta original, então não entendo de onde você está conseguindo isso.
Se houver uma exceção não tratada dentro de um bloco de manipulador de captura, o bloco finalmente será chamado exatamente zero vezes
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
Resultado:
C: \ usuários \ administrador \ documentos \ TestExceptionNesting \ bin \ Release> TestExceptionNesting.exe
na tentativa
na captura
Exceção não tratada: System.DivideByZeroException: tentativa de dividir por zero. em TestExceptionNesting.Program.Main (String [] args) em C: \ users \ administrator \ documents \ TestExceptionNesting \ TestExceptionNesting.cs: linha 22
C: \ usuários \ administrador \ documentos \ TestExceptionNesting \ bin \ release>
Fiz essa pergunta hoje em uma entrevista e o entrevistador continuou voltando "você tem certeza de que finalmente não foi chamado?" Eu não tinha certeza se era uma pergunta complicada ou se o entrevistador tinha outra coisa em mente e escreveu o código errado para eu depurar, então cheguei em casa e tentei (construir e executar, sem interação do depurador), apenas para colocar minha mente em descansar.
Testando com um aplicativo de console C #, o código finalmente foi executado após a exceção: A "caixa de diálogo Erro de aplicativo" existia e depois que você selecionava a opção "Fechar o programa", o bloco finalmente foi executado nessa janela do console. Mas definindo o ponto de ruptura dentro do bloco de código finalmente, nunca consigo atingi-lo. O depurador continua parando na instrução throw. Aqui está o meu código de teste:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}
Depurando no VS2010 - .NET Framework 4.0