Exceptions: Não use try-catch-finally
Essa semana estava revendo um trecho do ARDA (https://github.com/DXBrazil/Arda) e os primeiros issues e pull requests estavam relacionados com o tratamento de exceção. Por coincidência, nessa mesma semana, fui perguntado sobre as melhores práticas de Exceptions sobre como e quando usar.
Comecei olhando a documentação do C# sobre o try-catch-finally.
Try-catch-finally
/en-us/dotnet/csharp/language-reference/keywords/try-catch-finally
Nesse artigo, há o seguinte trecho de código:
Então, pergunto:
O que há de errado nesse exemplo?
Embora a linguagem permita a construção e a documentação confirma que é possível, sigo o pensamento de que a sintaxe try..catch..finally não deveria existir no C#. Na minha opinião, não se deve usar try-catch-finally. Essa é uma afirmação forte e, antes de que alguém se desespere, deixo explicar meu ponto de vista.
Por que não existe “finally” no C++?
Você sabia que a linguagem C++ suporta exceções e somente a construção try-catch? Não existe finally!
https://www.stroustrup.com/bs_faq2.html#finally
Why doesn't C++ provide a "finally" construct?
Resposta do Bjarne Stroustrup:
Because C++ supports an alternative that is almost always better: The "resource acquisition is initialization" technique (TC++PL3 section 14.4).
A linguagem do C++ adota o padrão de Resource Acquisition is Initialization (RAII) . Em outras palavras, os recursos devem ser desalocados dentro do destrutor das classes, dispensando o uso do finally.
Use try-catch
Quando lidamos com exceção, tratamos as exceptions através de blocos try-catch.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-catch
Não tem segredo: as exceções são capturadas pelo bloco catch para tratamento do erro.
Use try-finally
A linguagem suporta a construção try-finally para liberar os recursos alocados.
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally
Diferente do C++, o garbage collector do C# (.NET) é não-determinístico. Por isso, sempre garanta que os recursos são liberados no momento certo através do finally.
Não use try-catch-finally
A construção try-catch-finally mistura dois propósitos distintos no mesmo código. Por isso, deixe claro a intenção e use a sintaxe adequada com os blocos:
- try-catch: Tratar os erros e exceções
- try-finally: Liberar explicitamente os recursos
Reescrevi o trecho anterior usando try-catch-finally e, ao invés de melhorar o código, parece que ficou mais confuso:
Nesse momento, é natural encapsular o trecho do código de leitura de arquivo dentro de outra função. Veja como o código fica mais claro:
A função ReadFileBlock gerencia o objeto File, fazendo a alocação de recurso e liberando no finally.
Compare como ficou muito melhor que a versão try-catch-finally.
Conclusão
Nesse artigo, apresentei a ideia de evitar o try-catch-finally porque essa construção mistura os conceitos de tratamento de exceção e liberação de recurso. Ao invés disso, recomendo que use try-catch ou try-finally.
Comments
- Anonymous
November 07, 2017
A conclusão ficou estranha. Está escrito: "... apresentei a ideia de 'não' evitar o try-catch-finally".- Anonymous
November 13, 2017
Errei! Ja vou corrigir. Obrigado!
- Anonymous