Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Exceções são usadas para indicar que ocorreu um erro durante a execução do programa. Objetos de exceção que descrevem um erro são criados e, em seguida, lançados om a instrução ou expressão throw
. Em seguida, o runtime pesquisa o manipulador de exceção mais compatível.
Os programadores devem gerar exceções quando uma ou mais das seguintes condições forem verdadeiras:
O método não pode concluir sua funcionalidade definida. Por exemplo, se um parâmetro para um método tiver um valor inválido:
static void CopyObject(SampleClass original) { _ = original ?? throw new ArgumentException("Parameter cannot be null", nameof(original)); }
É feita uma chamada inadequada a um objeto, com base no estado do objeto. Um exemplo pode ser a tentativa de gravar em um arquivo somente leitura. Nos casos em que um estado de objeto não permite uma operação, gere uma instância de InvalidOperationException ou um objeto com base em uma derivação dessa classe. O código a seguir é um exemplo de um método que gera um objeto InvalidOperationException:
public class ProgramLog { FileStream logFile = null!; public void OpenLog(FileInfo fileName, FileMode mode) { } public void WriteLog() { if (!logFile.CanWrite) { throw new InvalidOperationException("Logfile cannot be read-only"); } // Else write data to the log and return. } }
Quando um argumento para um método causa uma exceção. Nesse caso, a exceção original deve ser capturada e uma instância ArgumentException deve ser criada. A exceção original deve ser passada para o construtor do ArgumentException como o parâmetro InnerException:
static int GetValueFromArray(int[] array, int index) { try { return array[index]; } catch (IndexOutOfRangeException e) { throw new ArgumentOutOfRangeException( "Parameter index is out of range.", e); } }
Nota
O exemplo anterior mostra como usar a propriedade
InnerException
. É intencionalmente simplificado. Na prática, você deve verificar se um índice está na faixa antes de usá-lo. Você pode usar essa técnica de encapsular uma exceção quando um membro de um parâmetro gera uma exceção que você não poderia prever antes de chamar o membro.
As exceções contêm uma propriedade chamada StackTrace. Essa cadeia de caracteres contém o nome dos métodos na pilha de chamadas atual, juntamente com o nome do arquivo e o número da linha em que a exceção foi gerada para cada método. Um objeto StackTrace é criado automaticamente pelo CLR (Common Language Runtime) no ponto da instrução throw
, de modo que as exceções devem ser lançadas do ponto em que o rastreamento de pilha deve começar.
Todas as exceções contêm uma propriedade chamada Message. Essa cadeia de caracteres deve ser definida para explicar o motivo da exceção. Informações confidenciais à segurança não devem ser colocadas no texto da mensagem. Além de Message, ArgumentException contém uma propriedade chamada ParamName que deve ser definida como o nome do argumento que causou a geração da exceção. Em um setter de propriedade, ParamName deve ser definido como value
.
Métodos públicos e protegidos geram exceções sempre que não conseguem concluir suas funções pretendidas. A classe de exceção gerada é a exceção mais específica disponível que atende às condições de erro. Essas exceções devem ser documentadas como parte da funcionalidade de classe, e classes ou atualizações derivadas para a classe original devem manter o mesmo comportamento para compatibilidade com versões anteriores.
Coisas a evitar ao lançar exceções
A lista a seguir identifica as práticas a serem evitadas ao lançar exceções:
- Não use exceções para alterar o fluxo de um programa como parte da execução comum. Use exceções para relatar e manipular condições de erro.
- As exceções não devem ser retornadas como um valor retornado ou um parâmetro em vez de serem lançadas.
- Não lance System.Exception, System.SystemException, System.NullReferenceException ou System.IndexOutOfRangeException intencionalmente de seu próprio código-fonte.
- Não crie exceções que podem ser lançadas no modo de depuração, mas não no modo de versão. Em vez disso, use o Debug Assert para identificar erros em tempo de execução durante a fase de desenvolvimento.
Exceções em métodos de retorno de tarefa
Os métodos declarados com o modificador async
têm algumas considerações especiais quando se trata de exceções. As exceções geradas em um método async
são armazenadas na tarefa retornada e não surgem até que, por exemplo, a tarefa seja aguardada. Para obter mais informações sobre exceções armazenadas, consulte exceções assíncronas.
Recomendamos que você valide argumentos e gere exceções correspondentes, como ArgumentException e ArgumentNullException, antes de inserir as partes assíncronas de seus métodos. Ou seja, essas exceções de validação devem surgir de forma síncrona antes do início do trabalho. O snippet de código a seguir mostra um exemplo em que, se as exceções forem geradas, as exceções ArgumentException surgirão de forma síncrona, enquanto a InvalidOperationException seria armazenada na tarefa retornada.
// Non-async, task-returning method.
// Within this method (but outside of the local function),
// any thrown exceptions emerge synchronously.
public static Task<Toast> ToastBreadAsync(int slices, int toastTime)
{
if (slices is < 1 or > 4)
{
throw new ArgumentException(
"You must specify between 1 and 4 slices of bread.",
nameof(slices));
}
if (toastTime < 1)
{
throw new ArgumentException(
"Toast time is too short.", nameof(toastTime));
}
return ToastBreadAsyncCore(slices, toastTime);
// Local async function.
// Within this function, any thrown exceptions are stored in the task.
static async Task<Toast> ToastBreadAsyncCore(int slices, int time)
{
for (int slice = 0; slice < slices; slice++)
{
Console.WriteLine("Putting a slice of bread in the toaster");
}
// Start toasting.
await Task.Delay(time);
if (time > 2_000)
{
throw new InvalidOperationException("The toaster is on fire!");
}
Console.WriteLine("Toast is ready!");
return new Toast();
}
}
Definir classes de exceção
Os programas podem lançar uma classe de exceção predefinida no namespace System (exceto quando observado anteriormente) ou criar suas próprias classes de exceção derivando de Exception. As classes derivadas devem definir pelo menos três construtores: um construtor sem parâmetros, um que define a propriedade da mensagem e outro que define as propriedades Message e InnerException. Por exemplo:
[Serializable]
public class InvalidDepartmentException : Exception
{
public InvalidDepartmentException() : base() { }
public InvalidDepartmentException(string message) : base(message) { }
public InvalidDepartmentException(string message, Exception inner) : base(message, inner) { }
}
Adicione novas propriedades à classe de exceção quando os dados fornecidos são úteis para resolver a exceção. Se novas propriedades forem adicionadas à classe de exceção derivada, ToString()
deverá ser substituída para retornar as informações adicionadas.
Especificação da linguagem C#
Para obter mais informações, veja Exceções e A declaração throw na Especificação da Linguagem C#. A especificação de idioma é a fonte definitiva para a sintaxe e o uso de C#.