try-catch (Referência de C#)try-catch (C# Reference)

A instrução try-catch consiste em um bloco try seguido por uma ou mais cláusulas catch, que especificam os manipuladores para diferentes exceções.The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions.

Quando uma exceção é lançada, o CLR (Common Language Runtime) procura a instrução catch que trata essa exceção.When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception. Se o método em execução no momento não contiver um bloco catch, o CLR procurará no método que chamou o método atual e assim por diante para cima na pilha de chamadas.If the currently executing method does not contain such a catch block, the CLR looks at the method that called the current method, and so on up the call stack. Se nenhum bloco catch for encontrado, o CLR exibirá uma mensagem de exceção sem tratamento para o usuário e interromperá a execução do programa.If no catch block is found, then the CLR displays an unhandled exception message to the user and stops execution of the program.

O bloco try contém o código protegido que pode causar a exceção.The try block contains the guarded code that may cause the exception. O bloco é executado até que uma exceção seja lançada ou ele seja concluído com êxito.The block is executed until an exception is thrown or it is completed successfully. Por exemplo, a tentativa a seguir de converter um objeto null gera a exceção NullReferenceException:For example, the following attempt to cast a null object raises the NullReferenceException exception:

object o2 = null;
try
{
    int i2 = (int)o2;   // Error
}

Embora a cláusula catch possa ser usada sem argumentos para capturar qualquer tipo de exceção, esse uso não é recomendado.Although the catch clause can be used without arguments to catch any type of exception, this usage is not recommended. Em geral, você deve capturar apenas as exceções das quais você sabe se recuperar.In general, you should only catch those exceptions that you know how to recover from. Portanto, você sempre deve especificar um argumento de objeto derivado de System.Exception, por exemplo:Therefore, you should always specify an object argument derived from System.Exception For example:

catch (InvalidCastException e)
{
}

É possível usar mais de uma cláusula catch específica na mesma instrução try-catch.It is possible to use more than one specific catch clause in the same try-catch statement. Nesse caso, a ordem das cláusulas catch é importante porque as cláusulas catch são examinadas em ordem.In this case, the order of the catch clauses is important because the catch clauses are examined in order. Capture as exceções mais específicas antes das menos específicas.Catch the more specific exceptions before the less specific ones. O compilador gerará um erro se você ordenar os blocos catch de forma que um bloco posterior nunca possa ser alcançado.The compiler produces an error if you order your catch blocks so that a later block can never be reached.

Usar argumentos catch é uma maneira de filtrar as exceções que deseja manipular.Using catch arguments is one way to filter for the exceptions you want to handle. Use também um filtro de exceção que examina melhor a exceção para decidir se ela deve ser manipulada.You can also use an exception filter that further examines the exception to decide whether to handle it. Se o filtro de exceção retornar falso, a pesquisa por um manipulador continuará.If the exception filter returns false, then the search for a handler continues.

catch (ArgumentException e) when (e.ParamName == "…")
{
}

Os filtros de exceção são preferíveis em relação à captura e relançamento (explicados abaixo) porque os filtros deixam a pilha intacta.Exception filters are preferable to catching and rethrowing (explained below) because filters leave the stack unharmed. Se um manipulador posterior despeja a pilha, você pode ver de onde a exceção originalmente veio, em vez de apenas o último lugar em que ela foi relançada.If a later handler dumps the stack, you can see where the exception originally came from, rather than just the last place it was rethrown. Um uso comum de expressões de filtro de exceção é o registro em log.A common use of exception filter expressions is logging. Crie um filtro que sempre retorna falso e que também gera um log; você pode registrar exceções conforme elas ocorrem sem precisar manipulá-las e gerá-las novamente.You can create a filter that always returns false that also outputs to a log, you can log exceptions as they go by without having to handle them and rethrow.

Uma instrução throw pode ser usada em um bloco catch para relançar a exceção que foi capturada pela instrução catch.A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement. O exemplo a seguir extrai informações de origem de uma exceção IOException e, em seguida, lança a exceção para o método pai.The following example extracts source information from an IOException exception, and then throws the exception to the parent method.

catch (FileNotFoundException e)
{
    // FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
    // Extract some information from this exception, and then
    // throw it to the parent method.
    if (e.Source != null)
        Console.WriteLine("IOException source: {0}", e.Source);
    throw;
}

Você pode capturar uma exceção e lançar uma exceção diferente.You can catch one exception and throw a different exception. Quando fizer isso, especifique a exceção capturada como a exceção interna, como mostrado no exemplo a seguir.When you do this, specify the exception that you caught as the inner exception, as shown in the following example.

catch (InvalidCastException e)
{
    // Perform some action here, and then throw a new exception.
    throw new YourCustomException("Put your error message here.", e);
}

Você pode também relançar uma exceção quando uma determinada condição for verdadeira, conforme mostrado no exemplo a seguir.You can also re-throw an exception when a specified condition is true, as shown in the following example.

catch (InvalidCastException e)
{
    if (e.Data == null)
    {
        throw;
    }
    else
    {
        // Take some action.
    }
}

Observação

Também é possível usar um filtro de exceção para obter um resultado semelhante em um modo geralmente mais limpo (além de não modificar a pilha, conforme explicado anteriormente neste documento).It is also possible to use an exception filter to get a similar result in an often cleaner fashion (as well as not modifying the stack, as explained earlier in this document). O exemplo a seguir tem um comportamento semelhante para chamadores como no exemplo anterior.The following example has a similar behavior for callers as the previous example. A função gera a InvalidCastException novamente para o chamador quando e.Data é null.The function throws the InvalidCastException back to the caller when e.Data is null.

catch (InvalidCastException e) when (e.Data != null)
{
    // Take some action.
}

De dentro de um bloco try, inicialize somente as variáveis que são declaradas nele.From inside a try block, initialize only variables that are declared therein. Caso contrário, uma exceção pode ocorrer antes da conclusão da execução do bloco.Otherwise, an exception can occur before the execution of the block is completed. Por exemplo, no exemplo de código a seguir, a variável n é inicializada dentro do bloco try.For example, in the following code example, the variable n is initialized inside the try block. Uma tentativa de usar essa variável fora do bloco try na instrução Write(n) gerará um erro de compilador.An attempt to use this variable outside the try block in the Write(n) statement will generate a compiler error.

static void Main()
{
    int n;
    try
    {
        // Do not initialize this variable here.
        n = 123;
    }
    catch
    {
    }
    // Error: Use of unassigned local variable 'n'.
    Console.Write(n);
}

Para obter mais informações sobre catch, consulte try-catch-finally.For more information about catch, see try-catch-finally.

Exceções em métodos assíncronosExceptions in async methods

Um método assíncrono é marcado por um modificador async e geralmente contém uma ou mais expressões ou instruções await.An async method is marked by an async modifier and usually contains one or more await expressions or statements. Uma expressão await aplica o operador await a um Task ou Task<TResult>.An await expression applies the await operator to a Task or Task<TResult>.

Quando o controle atinge um await no método assíncrono, o progresso no método é suspenso até que a tarefa aguardada seja concluída.When control reaches an await in the async method, progress in the method is suspended until the awaited task completes. Quando a tarefa for concluída, a execução poderá ser retomada no método.When the task is complete, execution can resume in the method. Para obter mais informações, consulte programação assíncrona com Async e Await.For more information, see Asynchronous programming with async and await.

A tarefa concluída para a qual await é aplicada pode estar em um estado de falha devido a uma exceção sem tratamento no método que retorna a tarefa.The completed task to which await is applied might be in a faulted state because of an unhandled exception in the method that returns the task. Aguardar a tarefa gera uma exceção.Awaiting the task throws an exception. Uma tarefa também poderá terminar em um estado cancelado se o processo assíncrono que a retorna for cancelado.A task can also end up in a canceled state if the asynchronous process that returns it is canceled. Aguardar uma tarefa cancelada lança um OperationCanceledException .Awaiting a canceled task throws an OperationCanceledException.

Para capturar a exceção, aguarde a tarefa em um bloco try e capture a exceção no bloco catch associado.To catch the exception, await the task in a try block, and catch the exception in the associated catch block. Para obter um exemplo, confira a seção Exemplo de método assíncrono.For an example, see the Async method example section.

Uma tarefa pode estar em um estado de falha porque ocorreram várias exceções no método assíncrono esperado.A task can be in a faulted state because multiple exceptions occurred in the awaited async method. Por exemplo, a tarefa pode ser o resultado de uma chamada para Task.WhenAll.For example, the task might be the result of a call to Task.WhenAll. Quando você espera uma tarefa, somente uma das exceções é capturada e não é possível prever qual exceção será capturada.When you await such a task, only one of the exceptions is caught, and you can't predict which exception will be caught. Para obter um exemplo, confira a seção Exemplo de Task.WhenAll.For an example, see the Task.WhenAll example section.

ExemploExample

No exemplo a seguir, o bloco try contém uma chamada para o método ProcessString que pode causar uma exceção.In the following example, the try block contains a call to the ProcessString method that may cause an exception. A cláusula catch contém o manipulador de exceção que apenas exibe uma mensagem na tela.The catch clause contains the exception handler that just displays a message on the screen. Quando instrução throw é chamada de dentro de ProcessString, o sistema procura a instrução catch e exibe a mensagem Exception caught.When the throw statement is called from inside ProcessString, the system looks for the catch statement and displays the message Exception caught.

class TryFinallyTest
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        string s = null; // For demonstration purposes.

        try
        {
            ProcessString(s);
        }
        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
        }
    }
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
   at TryFinallyTest.Main() Exception caught.
 * */

Exemplo de dois blocos catchTwo catch blocks example

No exemplo a seguir, dois blocos catch são usados e a exceção mais específica, que vem primeiro, é capturada.In the following example, two catch blocks are used, and the most specific exception, which comes first, is caught.

Para capturar a exceção menos específica, você pode substituir a instrução throw em ProcessString pela seguinte instrução: throw new Exception().To catch the least specific exception, you can replace the throw statement in ProcessString with the following statement: throw new Exception().

Se você colocar o bloco catch menos específica primeiro no exemplo, a seguinte mensagem de erro aparecerá: A previous catch clause already catches all exceptions of this or a super type ('System.Exception').If you place the least-specific catch block first in the example, the following error message appears: A previous catch clause already catches all exceptions of this or a super type ('System.Exception').

class ThrowTest3
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        try
        {
            string s = null;
            ProcessString(s);
        }
        // Most specific:
        catch (ArgumentNullException e)
        {
            Console.WriteLine("{0} First exception caught.", e);
        }
        // Least specific:
        catch (Exception e)
        {
            Console.WriteLine("{0} Second exception caught.", e);
        }
    }
}
/*
 Output:
 System.ArgumentNullException: Value cannot be null.
 at Test.ThrowTest3.ProcessString(String s) ... First exception caught.
*/

Exemplo de método assíncronoAsync method example

O exemplo a seguir ilustra o tratamento de exceção para métodos assíncronos.The following example illustrates exception handling for async methods. Para capturar uma exceção que lança uma tarefa assíncrona, coloque a expressão await em um bloco try e capture a exceção em um bloco catch.To catch an exception that an async task throws, place the await expression in a try block, and catch the exception in a catch block.

Remova a marca de comentário da linha throw new Exception no exemplo para demonstrar o tratamento de exceção.Uncomment the throw new Exception line in the example to demonstrate exception handling. A propriedade IsFaulted da tarefa é definida para True, a propriedade Exception.InnerException da tarefa é definida para a exceção e a exceção é capturada em um bloco catch.The task's IsFaulted property is set to True, the task's Exception.InnerException property is set to the exception, and the exception is caught in the catch block.

Remova a marca de comentário da linha throw new OperationCanceledException para demonstrar o que acontece quando você cancela um processo assíncrono.Uncomment the throw new OperationCanceledException line to demonstrate what happens when you cancel an asynchronous process. A propriedade IsCanceled da tarefa é definida para true e a exceção é capturada no bloco catch.The task's IsCanceled property is set to true, and the exception is caught in the catch block. Em algumas condições que não se aplicam a este exemplo, a propriedade IsFaulted da tarefa é definida para true e IsCanceled é definido para false.Under some conditions that don't apply to this example, the task's IsFaulted property is set to true and IsCanceled is set to false.

public async Task DoSomethingAsync()
{
    Task<string> theTask = DelayAsync();

    try
    {
        string result = await theTask;
        Debug.WriteLine("Result: " + result);
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception Message: " + ex.Message);
    }
    Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
    Debug.WriteLine("Task IsFaulted:  " + theTask.IsFaulted);
    if (theTask.Exception != null)
    {
        Debug.WriteLine("Task Exception Message: "
            + theTask.Exception.Message);
        Debug.WriteLine("Task Inner Exception Message: "
            + theTask.Exception.InnerException.Message);
    }
}

private async Task<string> DelayAsync()
{
    await Task.Delay(100);

    // Uncomment each of the following lines to
    // demonstrate exception handling.

    //throw new OperationCanceledException("canceled");
    //throw new Exception("Something happened.");
    return "Done";
}

// Output when no exception is thrown in the awaited method:
//   Result: Done
//   Task IsCanceled: False
//   Task IsFaulted:  False

// Output when an Exception is thrown in the awaited method:
//   Exception Message: Something happened.
//   Task IsCanceled: False
//   Task IsFaulted:  True
//   Task Exception Message: One or more errors occurred.
//   Task Inner Exception Message: Something happened.

// Output when a OperationCanceledException or TaskCanceledException
// is thrown in the awaited method:
//   Exception Message: canceled
//   Task IsCanceled: True
//   Task IsFaulted:  False

Exemplo de Task.WhenAllTask.WhenAll example

O exemplo a seguir ilustra a manipulação de exceção em que várias tarefas podem resultar em várias exceções.The following example illustrates exception handling where multiple tasks can result in multiple exceptions. O bloco try aguarda a tarefa que é retornada por uma chamada para Task.WhenAll.The try block awaits the task that's returned by a call to Task.WhenAll. A tarefa é concluída quando as três tarefas às quais WhenAll se aplica são concluídas.The task is complete when the three tasks to which WhenAll is applied are complete.

Cada uma das três tarefas causa uma exceção.Each of the three tasks causes an exception. O bloco catch itera por meio de exceções, que são encontradas na propriedade Exception.InnerExceptions da tarefa que foi retornada por Task.WhenAll.The catch block iterates through the exceptions, which are found in the Exception.InnerExceptions property of the task that was returned by Task.WhenAll.

public async Task DoMultipleAsync()
{
    Task theTask1 = ExcAsync(info: "First Task");
    Task theTask2 = ExcAsync(info: "Second Task");
    Task theTask3 = ExcAsync(info: "Third Task");

    Task allTasks = Task.WhenAll(theTask1, theTask2, theTask3);

    try
    {
        await allTasks;
    }
    catch (Exception ex)
    {
        Debug.WriteLine("Exception: " + ex.Message);
        Debug.WriteLine("Task IsFaulted: " + allTasks.IsFaulted);
        foreach (var inEx in allTasks.Exception.InnerExceptions)
        {
            Debug.WriteLine("Task Inner Exception: " + inEx.Message);
        }
    }
}

private async Task ExcAsync(string info)
{
    await Task.Delay(100);

    throw new Exception("Error-" + info);
}

// Output:
//   Exception: Error-First Task
//   Task IsFaulted: True
//   Task Inner Exception: Error-First Task
//   Task Inner Exception: Error-Second Task
//   Task Inner Exception: Error-Third Task

Especificação da linguagem C#C# language specification

Para obter mais informações, confira a seção A instrução try da Especificação da linguagem C#.For more information, see The try statement section of the C# language specification.

Confira tambémSee also