try-catch (Referencia de C#)try-catch (C# Reference)

La instrucción try-catch consta de un bloque try seguido de una o más cláusulas catch que especifican controladores para diferentes excepciones.The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions.

ComentariosRemarks

Cuando se produce una excepción, Common Language Runtime (CLR) busca la instrucción catch que controla esta excepción.When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception. Si el método que se ejecuta actualmente no contiene un bloque catch, CLR busca el método que llamó el método actual, y así sucesivamente hasta la pila de llamadas.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. Si no existe ningún bloque catch, CLR muestra al usuario un mensaje de excepción no controlada y detiene la ejecución del programa.If no catch block is found, then the CLR displays an unhandled exception message to the user and stops execution of the program.

El bloque try contiene el código protegido que puede producir la excepción.The try block contains the guarded code that may cause the exception. El bloque se ejecuta hasta que se produce una excepción o hasta que se completa correctamente.The block is executed until an exception is thrown or it is completed successfully. Por ejemplo, el intento siguiente de convertir un objeto null produce la excepción NullReferenceException:For example, the following attempt to cast a null object raises the NullReferenceException exception:

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

Aunque la cláusula catch puede utilizarse sin argumentos para detectar cualquier tipo de excepción, no se recomienda este uso.Although the catch clause can be used without arguments to catch any type of exception, this usage is not recommended. En general, solo debe convertir las excepciones que sabe cómo recuperar.In general, you should only catch those exceptions that you know how to recover from. Por lo tanto, debe especificar siempre un argumento de objeto derivado de System.Exception Por ejemplo:Therefore, you should always specify an object argument derived from System.Exception For example:

catch (InvalidCastException e)
{
}

Es posible utilizar más de una cláusula catch específica en la misma instrucción try-catch.It is possible to use more than one specific catch clause in the same try-catch statement. En este caso, el orden de las cláusulas catch es importante, puesto que las cláusulas catch se examinan por orden.In this case, the order of the catch clauses is important because the catch clauses are examined in order. Detectar las excepciones más específicas antes que las menos específicas.Catch the more specific exceptions before the less specific ones. El compilador genera un error si ordena los bloques de detección para que un bloque posterior nunca pueda alcanzarse.The compiler produces an error if you order your catch blocks so that a later block can never be reached.

La utilización de los argumentos catch es una manera de filtrar las excepciones que desea controlar.Using catch arguments is one way to filter for the exceptions you want to handle. También se puede usar una expresión de filtro que examine aún más la excepción para decidir si controlarla.You can also use an exception filter that further examines the exception to decide whether to handle it. Si la expresión de filtro devuelve false, prosigue la búsqueda de un controlador.If the exception filter returns false, then the search for a handler continues.

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

Los filtros de excepción son preferibles para detectar y volver a producir (se explica a continuación) porque los filtros dejan la pila intacta.Exception filters are preferable to catching and rethrowing (explained below) because filters leave the stack unharmed. Si un controlador posterior vuelca la pila, puede ver la procedencia original de la excepción, más que solo la ubicación en la que se volvió a producir.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. Un uso común de las expresiones de filtro de excepciones es el registro.A common use of exception filter expressions is logging. Puede crear una función de filtro que siempre devuelva false y que también resulte en un registro, o bien puede registrar excepciones a medida que se produzcan sin tener que controlarlas y volver a generarlas.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.

Se puede usar una instrucción throw en un bloque catch para volver a iniciar la excepción detectada por la instrucción catch.A throw statement can be used in a catch block to re-throw the exception that is caught by the catch statement. En el ejemplo siguiente se extrae información de origen de una excepción IOException y, a continuación, se produce la excepción al método principal.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;
}

Puede capturar una excepción y producir una excepción diferente.You can catch one exception and throw a different exception. Al hacerlo, especifique la excepción que detectó como excepción interna, tal como se muestra en el ejemplo siguiente.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);
}

También se puede volver a producir una excepción sin una condición específica es true, tal y como se muestra en el ejemplo siguiente.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.
    }
}

Nota

También es posible usar un filtro de excepción para obtener un resultado similar de una forma generalmente más limpia (además de no modificar la pila, tal y como se explicó anteriormente en este 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). El ejemplo siguiente tiene un comportamiento similar para los autores de llamada que el ejemplo anterior.The following example has a similar behavior for callers as the previous example. La función inicia la excepción InvalidCastException de vuelta al autor de la llamada cuando e.Data es 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.
}

Desde dentro de un bloque try, solo deben inicializarse las variables que se declaran en el mismo.From inside a try block, initialize only variables that are declared therein. De lo contrario, puede ocurrir una excepción antes de que se complete la ejecución del bloque.Otherwise, an exception can occur before the execution of the block is completed. Por ejemplo, en el siguiente ejemplo de código, la variable n se inicializa dentro del bloque try.For example, in the following code example, the variable n is initialized inside the try block. Un intento de utilizar esta variable fuera del bloque try en la instrucción Write(n) generará un error del 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 obtener más información sobre la captura,vea try-catch-finally (try-catch-finally [Referencia de C#]).For more information about catch, see try-catch-finally.

Excepciones en métodos asincrónicosExceptions in Async Methods

Un método asincrónico está marcado por un modificador async y normalmente contiene una o más instrucciones o expresiones await.An async method is marked by an async modifier and usually contains one or more await expressions or statements. Una expresión await aplica el operador await a Task o Task<TResult>.An await expression applies the await operator to a Task or Task<TResult>.

Cuando el control alcanza un await en el método asincrónico, el progreso del método se suspende hasta que la tarea esperada se completa.When control reaches an await in the async method, progress in the method is suspended until the awaited task completes. Cuando se completa la tarea, la ejecución puede reanudarse en el método.When the task is complete, execution can resume in the method. Para más información, vea Programación asincrónica con Async y Await y Controlar el flujo en los programas asincrónicos.For more information, see Asynchronous Programming with async and await and Control Flow in Async Programs.

La tarea completada a la que se aplica await puede encontrarse en un estado de error debido a una excepción no controlada en el método que devuelve la tarea.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. La espera de la tarea produce una excepción.Awaiting the task throws an exception. Una tarea también puede terminar en un estado cancelado si se cancela el proceso asincrónico que devuelve.A task can also end up in a canceled state if the asynchronous process that returns it is canceled. La espera de una tarea cancelada devuelve una OperationCanceledException.Awaiting a canceled task throws an OperationCanceledException. Para obtener más información sobre cómo cancelar un proceso asincrónico, vea Ajustar una aplicación asincrónica (C# y Visual Basic).For more information about how to cancel an asynchronous process, see Fine-Tuning Your Async Application.

Para detectar la excepción, espere la tarea en un bloque try y detéctela en el bloque asociado catch.To catch the exception, await the task in a try block, and catch the exception in the associated catch block. Para obtener un ejemplo, vea la sección "Ejemplo".For an example, see the "Example" section.

Una tarea puede encontrarse en un estado de error debido a que ocurrieron varias excepciones en el método asincrónico esperado.A task can be in a faulted state because multiple exceptions occurred in the awaited async method. Por ejemplo, la tarea podría ser el resultado de una llamada a Task.WhenAll.For example, the task might be the result of a call to Task.WhenAll. Cuando espera una tarea de este tipo, solo se captura una de las excepciones y no puede predecir qué excepción se capturará.When you await such a task, only one of the exceptions is caught, and you can't predict which exception will be caught. Para obtener un ejemplo, vea la sección "Ejemplo".For an example, see the "Example" section.

EjemploExample

En el ejemplo siguiente, el bloque try contiene una llamada al método ProcessString que puede causar una excepción.In the following example, the try block contains a call to the ProcessString method that may cause an exception. La cláusula catch contiene el controlador de excepciones que muestra un mensaje en la pantalla.The catch clause contains the exception handler that just displays a message on the screen. Cuando la instrucción throw se llama desde dentro MyMethod, el sistema busca la instrucción catch y muestra el mensaje Exception caught.When the throw statement is called from inside MyMethod, 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.
 * */

EjemploExample

En el ejemplo siguiente, se utilizan dos bloques de detección y la excepción más específica, que es la que aparece primero, es la que se captura.In the following example, two catch blocks are used, and the most specific exception, which comes first, is caught.

Para capturar la excepción menos específica, puede sustituir la instrucción throw en ProcessString por la siguiente instrucción: throw new Exception().To catch the least specific exception, you can replace the throw statement in ProcessString with the following statement: throw new Exception().

Si coloca primero el bloque catch menos específico en el ejemplo, aparece el siguiente mensaje de error: 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.
*/

EjemploExample

En el ejemplo siguiente se muestra el control de excepciones de los métodos asincrónicos.The following example illustrates exception handling for async methods. Para capturar una excepción que produce una tarea asincrónica, coloque la expresión await en un bloque try y capture la excepción en un bloque 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.

Quite la marca de comentario de la línea throw new Exception en el ejemplo para demostrar el control de excepciones.Uncomment the throw new Exception line in the example to demonstrate exception handling. La propiedad de la tarea IsFaulted se establece en True, la propiedad de la tarea Exception.InnerException se establece en la excepción, y la excepción se captura en el bloque 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.

Quite la marca de comentario de la línea throw new OperationCanceledException para ver lo que pasa cuando se cancela un proceso asincrónico.Uncomment the throw new OperationCanceledException line to demonstrate what happens when you cancel an asynchronous process. La propiedad de la tarea IsCanceled se establece en true, y la excepción se captura en el bloque catch.The task's IsCanceled property is set to true, and the exception is caught in the catch block. En algunas condiciones que no son aplicables a este ejemplo, la propiedad de la tarea IsFaulted se establece en true y IsCanceled se establece en 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

EjemploExample

En el ejemplo siguiente se muestra el control de excepciones en el que varias tareas pueden producir varias excepciones.The following example illustrates exception handling where multiple tasks can result in multiple exceptions. El bloque try espera la tarea devuelta por una llamada a Task.WhenAll.The try block awaits the task that's returned by a call to Task.WhenAll. La tarea se completa cuando se hayan completado las tres tareas a las que se aplica el método WhenAll.The task is complete when the three tasks to which WhenAll is applied are complete.

Cada una de las tres tareas produce una excepción.Each of the three tasks causes an exception. El bloque catch se itera a través de las excepciones, que se encuentran en la propiedad Exception.InnerExceptions de la tarea devuelta 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

Especificación del lenguaje C#C# language specification

Para obtener más información, consulte la Especificación del lenguaje C#.For more information, see the C# Language Specification. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.The language specification is the definitive source for C# syntax and usage.

Vea tambiénSee also