Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Em C#, erros no programa em tempo de execução são propagados através do programa usando um mecanismo chamado exceções. As exceções são lançadas pelo código que encontra um erro e capturadas pelo código que pode corrigir o erro. As exceções podem ser lançadas pelo tempo de execução do .NET ou pelo código em um programa. Uma vez que uma exceção é lançada, ela propaga-se pela pilha de chamadas até que seja encontrada uma instrução catch
para a exceção. As exceções não detetadas são tratadas por um manipulador de exceções genérico fornecido pelo sistema que exibe uma caixa de diálogo.
As exceções são representadas por classes derivadas de Exception. Essa classe identifica o tipo de exceção e contém propriedades que têm detalhes sobre a exceção. Lançar uma exceção envolve criar uma instância de uma classe derivada de exceção, configurar opcionalmente as propriedades da exceção e, em seguida, lançar o objeto usando a throw
palavra-chave. Por exemplo:
class CustomException : Exception
{
public CustomException(string message)
{
}
}
private static void TestThrow()
{
throw new CustomException("Custom exception in TestThrow()");
}
Após uma exceção ser lançada, o tempo de execução verifica a declaração atual para verificar se está dentro de um bloco try
. Se for, todos os catch
blocos associados ao try
bloco são verificados para ver se eles podem capturar a exceção.
Catch
os blocos normalmente especificam tipos de exceção; Se o tipo do catch
bloco for o mesmo tipo que a exceção, ou uma classe base da exceção, o catch
bloco pode manipular o método. Por exemplo:
try
{
TestThrow();
}
catch (CustomException ex)
{
System.Console.WriteLine(ex.ToString());
}
Se a instrução que lança uma exceção não estiver dentro de um try
bloco ou se o try
bloco que o encerra não tiver um bloco catch
correspondente, o ambiente de execução verificará se o método de chamada possui uma instrução try
e blocos catch
. O tempo de execução continua ao longo da pilha de chamadas, procurando por um bloco compatível catch
. Depois que o catch
bloco é encontrado e executado, o controle é passado para a próxima instrução após esse catch
bloco.
Uma try
instrução pode conter mais de um catch
bloco. A primeira catch
instrução que pode lidar com a exceção é executada, todas as instruções a seguir catch
, mesmo que sejam compatíveis, são ignoradas. Ordene os blocos de captura do mais específico (ou mais derivado) para o menos específico. Por exemplo:
using System;
using System.IO;
namespace Exceptions
{
public class CatchOrder
{
public static void Main()
{
try
{
using (var sw = new StreamWriter("./test.txt"))
{
sw.WriteLine("Hello");
}
}
// Put the more specific exceptions first.
catch (DirectoryNotFoundException ex)
{
Console.WriteLine(ex);
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
}
// Put the least specific exception last.
catch (IOException ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Done");
}
}
}
Antes de o bloco catch
ser executado, o tempo de execução verifica blocos finally
.
Finally
Os blocos permitem que o programador limpe qualquer estado ambíguo que possa sobrar de um bloco abortado ou libere try
quaisquer recursos externos (como identificadores gráficos, conexões de banco de dados ou fluxos de arquivos) sem esperar que o coletor de lixo no tempo de execução finalize os objetos. Por exemplo:
static void TestFinally()
{
FileStream? file = null;
//Change the path to something that works on your machine.
FileInfo fileInfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Closing the file allows you to reopen it immediately - otherwise IOException is thrown.
file?.Close();
}
try
{
file = fileInfo.OpenWrite();
Console.WriteLine("OpenWrite() succeeded");
}
catch (IOException)
{
Console.WriteLine("OpenWrite() failed");
}
}
Se WriteByte()
lançar uma exceção, o código no bloco try
que tenta reabrir o ficheiro falhará, se file.Close()
não for chamado, e o ficheiro permanecerá bloqueado. Como finally
os blocos são executados mesmo se uma exceção for lançada, o finally
bloco no exemplo anterior permite que o arquivo seja fechado corretamente e ajuda a evitar um erro.
Se nenhum bloco compatível catch
for encontrado na pilha de chamadas depois que uma exceção for lançada, uma das três coisas ocorrerá:
- Se a exceção estiver dentro de um finalizador, o finalizador será abortado e o finalizador base, se houver, será chamado.
- Se a pilha de chamadas contiver um construtor estático ou um inicializador de campo estático, um TypeInitializationException será lançado, com a exceção original atribuída à propriedade InnerException da nova exceção.
- Se o início do encadeamento for alcançado, o encadeamento será encerrado.