try-catch (Referencia de C#)

Actualización: noviembre 2007

La instrucción try-catch consta de un bloque try seguido de una o más cláusulas catch, las cuales especifican controladores para diferentes excepciones. Cuando se produce una excepción, Common Language Runtime (CLR) busca la instrucción catch que controla esta excepción. Si el método que se está ejecutando actualmente no contiene un bloque catch de este tipo, CLR examina el método que llamó al método actual y así sucesivamente en la pila de llamadas. Si no se encuentra ningún bloque catch, CLR muestra al usuario un mensaje de excepción no controlada y detiene la ejecución del programa.

El bloque try contiene el código protegido que puede causar la excepción. Este bloque se ejecuta hasta que se produce una excepción o hasta completarse satisfactoriamente. Por ejemplo, el siguiente intento de convertir un objeto null provoca la excepción NullReferenceException:

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. En general, sólo debe detectar las excepciones de las que sepa cómo recuperarse. Por lo tanto, debe especificar siempre un argumento de objeto derivado de System.Exception. Por ejemplo:

catch (InvalidCastException e) 
{
}

Es posible utilizar más de una cláusula catch específica en la misma instrucción try-catch. En este caso, el orden de las cláusulas catch es importante, ya que las cláusulas catch se examinan por orden. Las excepciones más específicas se capturan antes que las menos específicas. El compilador generará un error si ordena los bloques catch de forma que nunca se alcance un bloque posterior.

Se puede utilizar una instrucción throw en el bloque catch para volver a producir la excepción, la cual ha sido capturada por la instrucción catch. Por ejemplo:

catch (InvalidCastException e) 
{
    throw (e);    // Rethrowing exception e
}

También puede producir una nueva excepción. Cuando lo haga, especifique la excepción que detecta como la excepción interna:

catch (InvalidCastException e) 
{
   // Can do cleanup work here.
    throw new CustomException("Error message here.", e);
}

Si desea volver a producir la excepción que está siendo actualmente controlada por una cláusula catch sin parámetros, use la instrucción throw sin argumentos. Por ejemplo:

catch
{
    throw;
}

Dentro de un bloque try, inicialice sólo variables declaradas en su interior; en caso contrario, puede producirse una excepción antes de que se complete la ejecución del bloque. Por ejemplo, en el siguiente ejemplo de código, la variable x se inicializa dentro del bloque try. Al intentar utilizar esta variable fuera del bloque try en la instrucción Write(x), se generará el siguiente error del compilador: Uso de variable local no asignada.

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

Para obtener más información sobre catch, vea try-catch-finally.

Ejemplo

En este ejemplo, el bloque try contiene una llamada al método ProcessString que puede producir una excepción. La cláusula catch contiene el controlador de excepciones, el cual simplemente muestra un mensaje en la pantalla. Cuando se realiza la llamada a la instrucción throw desde dentro de MyMethod, el sistema busca la instrucción catch y muestra el mensaje 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.
     * */

En este ejemplo, se utilizan dos instrucciones catch. La excepción más específica, que aparece en primer lugar, se captura primero.

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 TryFinallyTest.Main() First exception caught.
*/

En el ejemplo anterior, si empieza con la cláusula catch menos específica, aparecerá el mensaje de error:

A previous catch clause already catches all exceptions of this or a super type ('System.Exception')

No obstante, para capturar la excepción menos específica, debe reemplazar la instrucción throw por la siguiente:

throw new Exception();

Especificación del lenguaje C#

Para obtener más información, vea las secciones siguientes de Especificación del lenguaje C#.

  • 5.3.3.13 Instrucciones Try-catch

  • 8.10 La instrucción try

  • 16 Excepciones

Vea también

Tareas

Cómo: Iniciar excepciones explícitamente

Conceptos

Guía de programación de C#

Referencia

Palabras clave de C#

The try, catch, and throw Statements

Instrucciones para el control de excepciones (Referencia de C#)

throw (Referencia de C#)

try-finally (Referencia de C#)

Otros recursos

Referencia de C#