Compartir a través de


Procedimientos recomendados para controlar excepciones

Un conjunto bien diseñado de bloques de código de control de errores puede hacer que un programa sea mucho más fuerte y menos propenso a interrupciones, porque la aplicación controla tales errores. A continuación se proporciona una lista de sugerencias sobre los procedimientos recomendados para controlar excepciones:

  • Saber cuándo configurar un bloque Try/Catch. Por ejemplo, se puede comprobar mediante programación si se da una condición que es probable que ocurra sin utilizar el control de errores. En otras situaciones, es aconsejable utilizar el control de excepciones para detectar una condición de error.

    En el ejemplo siguiente se usa una instrucción if para comprobar si se ha cerrado una conexión. Se puede usar este método en lugar de producir una excepción si la conexión no está cerrada.

       If conn.State <> ConnectionState.Closed Then
          conn.Close()
       End If
       if(conn.State != ConnectionState.Closed)
          conn.Close();
    

    En el ejemplo siguiente, se produce una excepción si la conexión no está cerrada.

       Try
          conn.Close()
       Catch ex As InvalidOperationException
          'Do something with the error or ignore it.
       End Try
       try {
         conn.Close();
       }
       catch(InvalidOperationException ex) {
         //Do something with the error or ignore it.
       }
    

    El método que se elija depende de la frecuencia con que se espera que se produzca el evento. Si el evento es muy excepcional y es un error (por ejemplo, un final de archivo inesperado), es mejor utilizar el control de excepciones porque se ejecuta menos código en el caso normal. Si el evento ocurre con frecuencia, es mejor utilizar el método de programación para comprobar si hay errores. En este caso, si se produce una excepción, se tarda más en controlarla.

  • Utilice bloques Try/Finally en torno a código que podría generar una excepción y centralice las instrucciones Catch en una ubicación. De esta manera, la instrucción Try genera la excepción, la instrucción Finally cierra o desasigna recursos y la instrucción Catch controla la excepción desde una ubicación central.

  • Ordene siempre las excepciones de los bloques Catch de la más específica a la menos. Con esta técnica se controla la excepción específica antes de que pase a un bloque Catch más general.

  • Termine los nombres de clases de excepción con la palabra "Exception". Por ejemplo:

    Public Class EmployeeListNotFoundException
        Inherits Exception
    public class MyFileNotFoundException : Exception {
    }
    
  • Cuando cree excepciones definidas por el usuario, debe garantizar que los metadatos de las excepciones están disponibles para el código que se ejecute de forma remota, incluso cuando se produzcan excepciones en distintos dominios de aplicación. Por ejemplo, supongamos que el dominio de aplicación A crea el dominio de aplicación B, que ejecuta código que produce una excepción. Para que el dominio de aplicación A detecte y controle la excepción correctamente, debe poder encontrar el ensamblado que contiene la excepción que produce el dominio de aplicación B. Si el dominio de aplicación B produce una excepción contenida en un ensamblado de su base pero no en la base de la aplicación del dominio de aplicación A, este último dominio no encontrará la excepción y Common Language Runtime producirá una FileNotFoundException. Para evitar esta situación, puede implementar el ensamblado que contiene la información de la excepción de dos maneras:

    • Ponga el ensamblado en una base de aplicación compartida por los dos dominios de aplicación.

      O bien,

    • Si los dominios no comparten una base de aplicación común, firme el ensamblado que contiene la información de la excepción con un nombre seguro e impleméntelo en la caché de ensamblados global.

  • En C# y C++, al menos utilice tres constructores comunes al crear sus propias clases de excepciones. Tiene un ejemplo en Utilizar excepciones definidas por el usuario.

  • Utilice, en la mayoría de los casos, los tipos de excepción predefinidos. Defina nuevos tipos de excepción sólo para escenarios de programación. Introduzca una nueva clase de excepción que permita al programador adoptar acciones distintas en código basado en la clase de excepción.

  • Para la mayoría de las aplicaciones, derive excepciones personalizadas de la clase Exception. Al principio, se pensaba que las excepciones personalizadas debían derivarse de la clase ApplicationException; sin embargo, en la práctica, se ha probado que esto no tiene ninguna importancia.

  • Incluya una cadena descriptiva localizada en todas las excepciones. Cuando el usuario ve un mensaje de error, deriva de la cadena descriptiva de la excepción que se produjo y no de la clase de excepción.

  • Utilice mensajes de error gramaticalmente correctos, incluida la puntuación de cierre. Cara oración de una cadena descriptiva de una excepción debe acabar con un punto.

  • Proporcione propiedades de Exception para el acceso mediante programación. Incluya información adicional en una excepción (además de la cadena descriptiva) sólo si hay un escenario de programación en que dicha información es útil.

  • Devuelva null para los casos de error muy frecuentes. Por ejemplo, File.Open devuelve null si no se encuentra el archivo, pero produce una excepción si el archivo está bloqueado.

  • Diseñe las clases de manera que nunca se produzca una excepción en el uso normal. Por ejemplo, una clase FileStream expone otra forma de determinar si se ha llegado al final del archivo. Así se evita la excepción que se produce si se lee más allá del final del archivo. En el ejemplo siguiente se muestra cómo leer hasta el final del archivo.

    Class FileRead
       Sub Open()
          Dim stream As FileStream = _
                        File.Open("myfile.txt", FileMode.Open)
            Dim b As Byte
            Dim result As Integer
            ' ReadByte returns -1 at EOF.
            Do 
               result = stream.ReadByte()
               If result = -1 Then Exit Do
                b = CByte(result)
                ' Do something.
            Loop
            ' Call stream.Close() here or in another method.
        End Sub 'Open
    End Class 'FileRead
    class FileRead {
        public void Open() {
            FileStream stream = File.Open("myfile.txt", FileMode.Open);
            byte b;
            int result;
            // ReadByte returns -1 at EOF.
            while ((result = stream.ReadByte()) != -1) {
                b = (byte)result;
                // Do something.
                }
            // Call stream.Close() here or in another method.
        }
    }
    
  • Produzca una InvalidOperationException cuando un conjunto de propiedades o una llamada a un método no sean adecuados al estado actual del objeto.

  • Produzca una ArgumentException o una clase derivada de ArgumentException si se pasan parámetros no válidos.

  • El seguimiento de pila comienza en la instrucción en que se produce la excepción y termina en la instrucción Catch que detecta la excepción. Tenga esto en cuenta para decidir dónde ubicar una instrucción Throw.

  • Utilice métodos de generador de excepciones. Es habitual que una clase produzca la misma excepción desde distintos lugares de su implementación. Para evitar el exceso de código, use métodos auxiliares que creen la excepción y la devuelvan. Por ejemplo:

    Class File
       Private fileName As String
    
       Public Function Read(bytes As Integer) As Byte()
          If Not ReadFile(handle, bytes) Then
             Throw NewFileIOException()
          End If
       End Function 'Read
    
       Function NewFileIOException() As FileException
          Dim description As String = __unknown ' Build localized string, including fileName.
          Return New FileException(description) '
       End Function 'NewFileIOException
    End Class 'File
    class File {
        string fileName;
        public byte[] Read(int bytes) {
            if (!ReadFile(handle, bytes))
                throw NewFileIOException();
        }
        FileException NewFileIOException() {
            string description = // Build localized string, including fileName.
            return new FileException(description);
         }
    }
    

    También puede utilizar el constructor de la excepción para generarla. Esto está más indicado para clases de excepción globales, como ArgumentException.

  • Produzca excepciones en lugar de devolver un código de error o HRESULT.

  • Cuando produzca una excepción, elimine los resultados intermedios. Los autores de llamadas deben poder asumir que no se producen efectos no deseados cuando se produce una excepción desde un método.

Vea también

Otros recursos

Controlar y generar excepciones