Learn C# Help

Tratamento de Exceções

Em programação, mesmo o código mais cuidadosamente escrito pode encontrar problemas inesperados durante a execução. Uma conexão de rede pode cair, um arquivo pode não ser encontrado ou um usuário pode inserir dados em um formato inválido. Esses eventos são chamados de exceções. O C# fornece um mecanismo robusto e estruturado para lidar com esses erros: o tratamento de exceções.

Analogia: O Chef de Cozinha Cauteloso

Imagine um chef de cozinha preparando um prato sofisticado. A execução da receita é o bloco try.

  • try: O chef tenta executar os passos da receita. Ele sabe que certas coisas podem dar errado: o molho pode queimar, ou ele pode deixar um prato cair.

  • catch: O chef tem planos de contingência. Se o molho queimar (catch (SauceBurnedException)), ele sabe exatamente como começar um novo rapidamente. Se um prato quebrar (catch (PlateDroppedException)), ele pega outro. Para qualquer outro desastre inesperado (catch (Exception)), seu plano geral é chamar o subchefe para avaliar a situação.

  • finally: Independentemente de a receita ser um sucesso ou um desastre, a cozinha precisa ser limpa no final do expediente. Esta limpeza é o bloco finally, que sempre acontece.

Essa abordagem estruturada garante que um pequeno acidente não arruíne todo o serviço do jantar. Da mesma forma, o tratamento de exceções impede que um erro de execução encerre abruptamente sua aplicação.

A Estrutura try-catch-finally

A sintaxe para o tratamento de exceções em C# envolve as palavras-chave try, catch e finally.

try { // Code that may throw an exception } catch (SpecificExceptionType ex) { // Code to handle the specific exception } catch (AnotherExceptionType ex) { // Code to handle another type of exception } finally { // Code that will always execute, regardless of whether an exception was thrown }

O Bloco try

Você deve colocar qualquer código que tenha o potencial de lançar uma exceção dentro de um bloco try. Se uma exceção ocorrer em qualquer ponto dentro deste bloco, a execução normal é interrompida e o Common Language Runtime (CLR) procura por um bloco catch compatível.

O Bloco catch

Um bloco catch é onde você lida com o erro. Você pode ter múltiplos blocos catch para um único bloco try, cada um projetado para lidar com um tipo específico de exceção.

É uma prática recomendada ordenar os blocos catch do mais específico para o mais genérico. Por exemplo, capturar FileNotFoundException antes de IOException, e IOException antes de Exception. Se o CLR não encontrar um catch específico para a exceção lançada, ele procurará por um catch que trate uma classe base da exceção.

public void ReadFile(string filePath) { try { string content = File.ReadAllText(filePath); Console.WriteLine("File content loaded successfully."); } catch (FileNotFoundException ex) { // Handle the case where the file does not exist Console.WriteLine($"Error: The file was not found at '{filePath}'."); Console.WriteLine($"Details: {ex.Message}"); } catch (IOException ex) { // Handle other I/O errors (e.g., permission issues) Console.WriteLine($"An I/O error occurred: {ex.Message}"); } catch (Exception ex) { // Catch any other unexpected exceptions Console.WriteLine($"An unexpected error occurred: {ex.Message}"); // It's often useful to re-throw if you can't handle it, // but only after logging the issue. // throw; } }

O Bloco finally

O bloco finally é opcional, mas extremamente útil. O código dentro dele é sempre executado, não importa o que aconteça no bloco try ou catch. Ele executará se:

  1. Nenhuma exceção ocorrer.

  2. Uma exceção ocorrer e for capturada por um catch.

  3. Uma exceção ocorrer e não for capturada.

Isso o torna o local ideal para liberar recursos não gerenciados, como fechar conexões de banco de dados, fechar streams de arquivos ou liberar handles de sistema.

public void ProcessData() { DatabaseConnection conn = new DatabaseConnection(); try { conn.Open(); // Perform database operations... } catch (DatabaseException ex) { Console.WriteLine($"A database error occurred: {ex.Message}"); } finally { // Ensure the connection is always closed if (conn.IsOpen) { conn.Close(); } } }

Lançando Exceções (throw)

Você também pode lançar exceções manualmente usando a palavra-chave throw. Isso é útil quando você detecta uma condição de erro em sua própria lógica de negócios ou quando deseja relançar uma exceção que capturou.

public void CreateUser(string username) { if (string.IsNullOrWhiteSpace(username)) { // Throw a new exception because the input is invalid throw new ArgumentNullException(nameof(username), "Username cannot be null or empty."); } // ... logic to create user }

Ao relançar uma exceção dentro de um bloco catch, use throw; em vez de throw ex;. Usar throw; preserva o stack trace original da exceção, o que é vital para a depuração, pois mantém o histórico de onde o erro se originou.

catch (SomeException ex) { // Log the exception _logger.LogError(ex, "An error occurred during some operation."); // Re-throw the original exception, preserving the stack trace throw; }

Referências Oficiais

Para um estudo mais aprofundado e detalhado, consulte a documentação oficial da Microsoft, que é a fonte definitiva sobre o assunto.

27 August 2025