É uma má prática retornar de dentro de um bloco try catch finalmente?

128

Então me deparei com um código esta manhã que se parecia com isso:

try
{
    x = SomeThingDangerous();
    return x;
}
catch (Exception ex)
{
    throw new DangerousException(ex);
}
finally
{
    CleanUpDangerousStuff();
}

Agora, esse código compila bem e funciona como deveria, mas simplesmente não parece correto retornar de dentro de um bloco try, especialmente se houver um associado finalmente.

Meu principal problema é o que acontece se o finalmente lança uma exceção por si próprio? Você tem uma variável retornada, mas também uma exceção para lidar ... então estou interessado em saber o que os outros pensam sobre retornar de dentro de um bloco try?

lomaxx
fonte
13
Um benefício desse estilo é que você não precisa declarar xfora do trybloco. Você pode manter sua declaração próxima ao seu uso.
David R Tribble

Respostas:

169

Não, não é uma prática ruim. Colocar returnonde faz sentido melhora a legibilidade e a capacidade de manutenção e torna seu código mais simples de entender. Você não deve se importar, pois o finallybloco será executado se uma returninstrução for encontrada.

Mehrdad Afshari
fonte
19

O finalmente será executado, não importa o quê, por isso não importa.

Ed S.
fonte
9
Não, na verdade, não está apenas sendo desconectado, existem algumas exceções chamadas exceções assíncronas, como StackOverflowException, ThreadAbortException e OutOfMemoryException, que podem fazer com que o bloco final não seja executado. Leia sobre regiões de execução restritas para lidar com esses cenários.
Mehrdad Afshari
O link a seguir explica: return Statement e tenta ... pegar ... finalmente Statement
amit jha
14

Pessoalmente, eu evitaria esse tipo de codificação, pois não sinto vontade de ver instruções de retorno antes de instruções finalmente.

Minha mente é simples e processa as coisas de maneira linear. Portanto, quando eu percorrer o código para execução a seco, terei a tendência de pensar que, uma vez que eu consiga alcançar a declaração de retorno, tudo o que segue não importa, o que obviamente está muito errado nesse caso (não que isso afete a declaração de retorno, mas quais seriam os efeitos colaterais).

Assim, eu organizaria o código para que a declaração de retorno sempre apareça após as instruções finalmente.

Conrad
fonte
9

Isso pode responder sua pergunta

O que realmente acontece em uma tentativa {return x; } finalmente {x = null; } declaração?

Ao ler essa pergunta, parece que você pode tentar outra estrutura de captura na declaração finalmente, se achar que isso pode gerar uma exceção. O compilador descobrirá quando retornar o valor.

Dito isso, pode ser melhor reestruturar seu código de qualquer maneira, apenas para não confundi-lo mais tarde ou alguém que também não tenha conhecimento disso.

Spencer Ruport
fonte
hmmm muito interessante. Então isso significa que é seguro, mas isso significa que deve ser evitado?
lomaxx
3
Pessoalmente, acho que dificulta um pouco a legibilidade do seu código e isso por si só seria suficiente para me fazer descobrir outra maneira de estruturar o código. Mas na verdade é apenas preferência pessoal.
Spencer Ruport
3
Eu tendo a concordar com sua preferência pessoal :)
lomaxx
Eu acho que o retorno é bom onde está. O método retornará o valor, a menos que uma exceção seja lançada; não importa se a exceção surgir no código de limpeza finalmente.
Lawrence Dol
Observe que a restrição de retorno de finalmente não está presente em Java (mas acho que a restrição é boa - parabéns ao C #).
Lawrence Dol
5

Funcionalmente, não há diferença.

No entanto, há uma razão para não fazer isso. Métodos mais longos com vários pontos de saída costumam ser mais difíceis de ler e analisar. Mas essa objeção tem mais a ver com declarações de retorno do que catch e, finalmente, bloqueia.

Ifeanyi Echeruo
fonte
Eu desafio isso, como você pode acabar com mais de nidificação que também torna mais difícil para ler um maior complexidade ciclomática
matt_lethargic
3

No seu exemplo, de qualquer maneira é equivalente, eu nem ficaria surpreso se o compilador gerasse o mesmo código. Se uma exceção ocorrer no bloco final, você terá os mesmos problemas, colocando a instrução de retorno em bloco ou fora dela.

A verdadeira questão é estilisticamente qual é a melhor. Eu gosto de escrever meus métodos para que exista apenas uma declaração de retorno; dessa forma, é mais fácil ver o fluxo sair do método; segue-se que eu também gosto de colocar a declaração de retorno por último, para que seja fácil ver que é o final do método e é isso que ele retorna.

Penso que, com a declaração de retorno tão bem colocada como a última, outras são menos propensas a vir e espalhar várias declarações de retorno em outras partes do método.

Esteja avisado
fonte