Compartir a través de


Control de excepciones

Las instrucciones siguientes ayudan a garantizar que su biblioteca controla las excepciones adecuadamente.

No controle los errores detectando excepciones no específicas, como System.Exception, System.SystemException, etc. en el código del marco de trabajo.

Puede detectar las excepciones cuando el propósito de hacerlo es volver a producirlas o transferir la excepción a un subproceso diferente. El ejemplo de código siguiente muestra un control de excepciones incorrecto.

Public Class BadExceptionHandlingExample1

    Public Sub DoWork()
        ' Do some work that might throw exceptions.
    End Sub

    Public Sub MethodWithBadHandler()
        Try
            DoWork()
        Catch e As Exception
            ' Handle the exception and 
            ' continue executing.
        End Try
    End Sub
End Class
public class BadExceptionHandlingExample1
{
    public void DoWork()
    {
        // Do some work that might throw exceptions.
    }
    public void MethodWithBadHandler()
    {
        try
        {
            DoWork();
        }
        catch (Exception e)
        {
            // Handle the exception and
            // continue executing.
        }
    }
}
public ref class BadExceptionHandlingExample1
{
public:
    void DoWork()
    {
        // Do some work that might throw exceptions.
    }

    void MethodWithBadHandler()
    {
        try
        {
            DoWork();
        }
        catch (Exception^ e)
        {
            // Handle the exception and
            // continue executing.
        }
    }
};

Evite controlar los errores detectando excepciones no específicas, como System.Exception, System.SystemException, etc. en el código del marco de trabajo. Hay casos en los que es aceptable controlar errores en aplicaciones, pero estos casos son poco frecuentes.

Una aplicación no debería controlar excepciones que pueden producir un estado inesperado o explotable. Si no puede predecir todas las causas posibles de una excepción y garantizar que el código malintencionado no puede aprovechar el estado de aplicación resistente, debe permitir que se cierre la aplicación en lugar de controlar la excepción.

No excluya ninguna excepción especial al realizar la detección con el fin de transferir las excepciones.

En lugar de crear listas de excepciones especiales en sus cláusulas catch, debería detectar sólo las excepciones que puede controlar legítimamente. Las excepciones que no se pueden controlar no se deberían tratar como casos especiales de controladores de excepciones no específicos. El ejemplo de código siguiente muestra una comprobación incorrecta de las excepciones especiales con el fin de volver a producirlas.

Public Class BadExceptionHandlingExample2

    Public Sub DoWork()
        ' Do some work that might throw exceptions.
    End Sub

    Public Sub MethodWithBadHandler()
        Try
            DoWork()
        Catch e As Exception
            If TypeOf e Is StackOverflowException Or _
               TypeOf e Is OutOfMemoryException Then
                Throw
            End If
        End Try
    End Sub
End Class
public class BadExceptionHandlingExample2
{
    public void DoWork()
    {
        // Do some work that might throw exceptions.
    }
    public void MethodWithBadHandler()
    {
        try
        {
            DoWork();
        }
        catch (Exception e)
        {
            if (e is StackOverflowException ||
                e is OutOfMemoryException)
                throw;
            // Handle the exception and
            // continue executing.
        }
    }
}
public ref class BadExceptionHandlingExample2
{
public:
    void DoWork()
    {
        // Do some work that might throw exceptions.
    }

    void MethodWithBadHandler()
    {
        try
        {
            DoWork();
        }
        catch (Exception^ e)
        {
            if (e->GetType() == StackOverflowException::typeid ||
                e->GetType() == OutOfMemoryException::typeid)
                throw;
            // Handle the exception and
            // continue executing.
        }
    }
};

Considere la posibilidad de detectar excepciones específicas cuando entienda por qué se producirán en un contexto determinado.

Debería detectar sólo las excepciones de las que se puede recuperar. Por ejemplo, una aplicación puede controlar la excepción FileNotFoundException resultante de un intento de abrir un archivo inexistente porque puede comunicar el problema al usuario y permitirle especificar otro nombre de archivo o crear el archivo. Una solicitud para abrir un archivo que genera una excepción ExecutionEngineException no debería controlarse porque la causa subyacente de dicha excepción no puede conocerse con ningún grado de certeza, y la aplicación no puede garantizar que es seguro continuar con la ejecución.

No realice un uso excesivo de las detecciones. Debería permitirse con frecuencia que las excepciones se propaguen en la pila de llamadas.

Detectar excepciones que no se pueden controlar legítimamente oculta información fundamental para la depuración.

Utilice try-finally y evite utilizar try-catch para la limpieza del código. En el código de excepción bien escrito, es mucho más frecuente encontrar bloques try-finally que try-catch.

El propósito de una cláusula catch es permitirle controlar las excepciones (por ejemplo, registrando un error recuperable). El propósito de una cláusula finally es permitirle ejecutar el código de limpieza independientemente de que se produjera una excepción. Si asigna recursos limitados o de gran consumo como conexiones de bases de datos o secuencias, debería incluir código para liberarlos dentro de un bloque finally.

Es preferible utilizar un inicio vacío al detectar y volver a producir una excepción. Ésta es la manera mejor de conservar la pila de llamadas de excepción.

El ejemplo de código siguiente muestra un método que puede producir una excepción. En ejemplos posteriores se hace referencia a este método.

Public Sub DoWork(ByVal anObject As Object)
    ' Do some work that might throw exceptions.
    If (anObject = Nothing) Then
        Throw New ArgumentNullException("anObject", "Specify a non-null argument.")
    End If
    ' Do work with o.
End Sub
public void DoWork(Object anObject)
{
    // Do some work that might throw exceptions.
    if (anObject == null)
    {
        throw new ArgumentNullException("anObject",
            "Specify a non-null argument.");
    }
    // Do work with o.
}
public:

    void DoWork(Object^ anObject)
    {
        // Do some work that might throw exceptions.
        if (anObject == nullptr)
        {
            throw gcnew ArgumentNullException("anObject",
                "Specify a non-null argument.");
        }
        // Do work with o.
    }

El ejemplo de código siguiente muestra cómo detectar una excepción y cómo especificarla incorrectamente al volver a producir la excepción. Esto hace que el seguimiento de la pila identifique el reinicio como la ubicación del error en lugar de señalar al método DoWork.

        Public Sub MethodWithBadCatch(ByVal anObject As Object)
            Try
                DoWork(anObject)

            Catch e As ArgumentNullException
                System.Diagnostics.Debug.Write(e.Message)
                ' This is wrong.
                Throw e
                ' Should be this:
                ' throw
            End Try
        End Sub

public void MethodWithBadCatch(Object anObject)
{
    try
    {
        DoWork(anObject);
    }
    catch (ArgumentNullException e)
    {
       System.Diagnostics.Debug.Write(e.Message);
       // This is wrong.
       throw e;
       // Should be this:
       // throw;
    }
}
void MethodWithBadCatch(Object^ anObject)
{
    try
    {
        DoWork(anObject);
    }
    catch (ArgumentNullException^ e)
    {
       System::Diagnostics::Debug::Write(e->Message);
       // This is wrong.
       throw e;
       // Should be this:
       // throw;
    }
}

No controle excepciones no conformes a CLS (excepciones que no se derivan de System.Exception) mediante un bloque catch sin parámetros. Los lenguajes que admiten excepciones que no se derivan de Exception tienen libertad para controlar estas excepciones no conformes a CLS.

La versión de 2.0 de .NET Framework contiene excepciones no conforme a CLS en una clase derivada de Exception.

Portions Copyright 2005 Microsoft Corporation. Reservados todos los derechos.

Portions Copyright Addison-Wesley Corporation. Reservados todos los derechos.

Para obtener más información sobre las directrices de diseño, consulte “las instrucciones de diseño de Framework: Convenciones, frases realizadas y modelos para libro de bibliotecas reutilizables de .NET” de Krzysztof Cwalina y Brad Abrams, publicados por Addison-Wesley, 2005.

Vea también

Otros recursos

Instrucciones de diseño para desarrollar bibliotecas de clases

Instrucciones de diseño de excepciones