Partilhar via


try-catch (referência de C#)

A instrução try-catch consiste em um bloco de try seguido por um ou mais cláusulas de catch , que especificam manipuladores para exceções diferentes.

Comentários

Quando uma exceção é lançada, o common language runtime (CLR) procura pela instrução de catch que trata essa exceção.Se o método atualmente em execução não contém um bloco de catch , o CLR examinar o método que chamou o método atual, e assim por diante até que a pilha de chamadas.Se nenhum bloco de catch for encontrado, o CLR exibe uma mensagem de exceção sem tratamento para o usuário e para a execução do programa.

O bloco de try contém o código protegido que pode causar a exceção.O bloco é executado até que uma exceção é lançada ou ela seja concluída com êxito.Por exemplo, a seguinte tentativa de converter um objeto de null gera a exceção de NullReferenceException :

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

Embora a cláusula de catch pode ser usada sem argumentos para capturar qualquer tipo de exceção, esse uso não é recomendado.Em geral, você deve apenas capturar essas exceções que você sabe recuperar.Portanto, você sempre deve especificar um argumento de objeto derivado de System.Exception por exemplo:

catch (InvalidCastException e) 
{
}

É possível usar mais de uma cláusula de catch específico na mesma instrução try-catch.Em esse caso, a ordem das cláusulas de catch é importante porque as cláusulas de catch são examinados em ordem.Capturar exceções mais específicas antes de menos específicas.O compilador gera um erro se você ordenar seus blocos catch para que um bloco posterior nunca pode ser alcançado.

Uma declaração de throw pode ser usada em um novamente throw do bloco de catch a exceção que é capturada pela instrução de catch .O exemplo extrai informações de origem de uma exceção de IOException , e gera a exceção para o método pai.

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.Quando você fizer isso, especifique a exceção que você capturou como a exceção interna, conforme mostrado no exemplo o seguir.

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

Você também pode reativar lance uma exceção quando uma condição especificada for verdadeira, conforme mostrado no exemplo o seguir.

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

De dentro de um bloco de try , somente inicializar variáveis que são declarados encontra-se.Caso contrário, uma exceção pode ocorrer antes da execução do bloco está concluída.Por exemplo, no exemplo de código a seguir, a variável n é inicializada dentro do bloco de try .Uma tentativa de usar essa variável fora do bloco de try na declaração de Write(n) irá gerar um erro do compilador.

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 a captura, consulte try-catch - final.

exceções em métodos de Async

Um método de async é marcado por um modificador de async e geralmente contém um ou mais expressões espera declarações ou.Uma expressão de espera aplica o operador de espere a Task ou a Task<TResult>.uma expressão de await não pode ocorrer em um bloco de catch ou em um bloco de finally .

Quando o controle atingir await no método de async, o método está em andamento suspenso até que a tarefa deve terminar.Quando a tarefa estiver concluída, a execução pode continuar no método.Para obter mais informações, consulte Programação com Async assíncrona e esperar (C# e Visual Basic) e Fluxo de controle em programas Async (C# e Visual Basic).

A tarefa que é concluída a await pode ser aplicado em um estado criticado por causa de uma exceção não tratada no método que retorna a tarefa.Aguardar que a tarefa gera uma exceção.Uma tarefa também pode acabar em um estado cancelado se o processo assíncrono que retorna ele serão canceladas.Esperar uma tarefa cancelada gera OperationCanceledException.Para obter mais informações sobre como cancelar um processo assíncrono, consulte Ajustando seu aplicativo Async (C# e Visual Basic).

Para capturar a exceção, aguardar que a tarefa em um bloco de try , e capturar a exceção no bloco associado de catch .Para um exemplo, consulte a seção “exemplo” de.

Uma tarefa pode estar em um estado criticado porque as várias exceções ocorreram no método de async esperado.Por exemplo, a tarefa pode ser o resultado de uma chamada a Task.WhenAll.Quando você espera uma tarefa, somente uma das exceções é capturado, e você não pode prever que será exceção capturada.Para um exemplo, consulte a seção “exemplo” de.

Exemplo

Em o exemplo, o bloco de try contém uma chamada para o método de ProcessString que pode causar uma exceção.A cláusula de catch contém o manipulador de exceção justas que exibe uma mensagem na tela.Quando a declaração de throw é chamada de dentro de MyMethod, o sistema procura pela instrução de catch e exibe a mensagem 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.
     * */

Em o exemplo a seguir, dois blocos catch são usados, e a exceção mais específica, que vem primeiro, é detectada.

Para capturar menos exceção específica, você pode substituir a instrução throw em ProcessString com a instrução a seguir: throw new Exception().

Se você colocar o menos bloco catch específico no primeiro exemplo, a seguinte mensagem de erro aparece: 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.
*/

O exemplo a seguir ilustra a manipulação de exceção para métodos de async.Para capturar uma exceção que o gera de uma tarefa de async, coloque a expressão de await em um bloco de try , e captura a exceção em um bloco de catch .

Tire comentários da linha de throw new Exception no exemplo para demonstrar manipulação de exceção.A propriedade de IsFaulted de tarefa é definida como True, a propriedade de Exception.InnerException de tarefa é definida como e exceção, a exceção é detectada no bloco de catch .

Tire comentários da linha de throw new OperationCancelledException para demonstrar o que acontece quando você cancelan processo assíncrono.A propriedade de IsCanceled de tarefa é definida como true, e a exceção é detectada no bloco de catch .Em algumas circunstâncias que não se aplicam a esse exemplo, a propriedade de IsFaulted de tarefa é definida como true e IsCanceled é definido como 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

O exemplo a seguir ilustra a manipulação de exceção onde várias tarefas podem resultar em várias exceções.O bloco de try espera a tarefa que é retornada pela chamada a Task.WhenAll.A tarefa é concluída quando as três tarefas que é aplicado a WhenAll está concluída.

Cada uma das três tarefas causa de uma exceção.O bloco de catch itera com exceções, que são encontrados na propriedade de Exception.InnerExceptions de tarefa que foi retornada por 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#

Para obter mais informações, consulte Especificação de linguagem do C# A especificação da linguagem é a fonte definitiva para a sintaxe e o uso da linguagem C#.

Consulte também

Tarefas

Como: lançar exceções explicitamente

Referência

Palavras-chave C#

Tente, catch e throw instruções (C++)

Instruções (C# Reference) de manipulação de exceção

Lançar (C# Reference)

try-finally (referência de C#)

Conceitos

Guia de programação do C#

Outros recursos

Referência de C#