Buscar..


Observaciones

Relacionado:

Atrapando una excepción

El código puede y debe lanzar excepciones en circunstancias excepcionales. Ejemplos de esto incluyen:

La persona que llama puede manejar estas excepciones "atrapándolas", y solo debe hacerlo cuando:

  • Realmente puede resolver la circunstancia excepcional o recuperarse adecuadamente, o;
  • Puede proporcionar un contexto adicional a la excepción que sería útil si la excepción necesita ser relanzada (las excepciones de relanzamiento son capturadas por los controladores de excepciones que se encuentran más arriba en la pila de llamadas)

Se debe tener en cuenta que elegir no capturar una excepción es perfectamente válido si la intención es que se maneje en un nivel superior.

La captura de una excepción se realiza envolviendo el código potencialmente lanzador en un bloque try { ... } siguiente manera, y capturando las excepciones que puede manejar en un bloque catch (ExceptionType) { ... } :

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}

Usando un bloque Finalmente

El bloque finally { ... } de try-finally o try-catch-finally siempre se ejecutará, independientemente de si se produjo una excepción o no (excepto cuando se ha lanzado una excepción StackOverflowException o se ha realizado una llamada a Environment.FailFast() ).

Puede utilizarse para liberar o limpiar los recursos adquiridos en el bloque try { ... } forma segura.

Console.Write("Please enter a filename: ");
string filename = Console.ReadLine();

Stream fileStream = null;

try
{
    fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
    Console.WriteLine("File '{0}' could not be found.", filename);
}
finally
{
    if (fileStream != null)
    {
        fileStream.Dispose();
    }
}

Atrapar y volver a captar excepciones.

Cuando desea capturar una excepción y hacer algo, pero no puede continuar la ejecución del bloque de código actual debido a la excepción, es posible que desee volver a emitir la excepción al siguiente controlador de excepciones en la pila de llamadas. Hay buenas y malas maneras de hacer esto.

private static void AskTheUltimateQuestion()
{
    try
    {
        var x = 42;
        var y = x / (x - x); // will throw a DivideByZeroException

        // IMPORTANT NOTE: the error in following string format IS intentional
        // and exists to throw an exception to the FormatException catch, below
        Console.WriteLine("The secret to life, the universe, and everything is {1}", y); 
    }
    catch (DivideByZeroException)
    {
        // we do not need a reference to the exception
        Console.WriteLine("Dividing by zero would destroy the universe.");

        // do this to preserve the stack trace:
        throw;
    }
    catch (FormatException ex)
    {
        // only do this if you need to change the type of the Exception to be thrown 
        // and wrap the inner Exception

        // remember that the stack trace of the outer Exception will point to the
        // next line

        // you'll need to examine the InnerException property to get the stack trace
        // to the line that actually started the problem

        throw new InvalidOperationException("Watch your format string indexes.", ex);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Something else horrible happened. The exception: " + ex.Message);

        // do not do this, because the stack trace will be changed to point to
        // this location instead of the location where the exception
        // was originally thrown:
        throw ex; 
    }
}

static void Main()
{
    try
    {
        AskTheUltimateQuestion();
    }
    catch
    {
        // choose this kind of catch if you don't need any information about 
        // the exception that was caught

        // this block "eats" all exceptions instead of rethrowing them
    }
}

Puede filtrar por tipo de excepción e incluso por propiedades de excepción (nuevo en C # 6.0, un poco más disponible en VB.NET (citación necesaria)):

Documentación / C # / nuevas funcionalidades

Filtros de excepción

Dado que las excepciones de C # 6.0 se pueden filtrar usando el operador when .

Esto es similar a usar un simple if pero no desenrolla la pila si no se cumple la condición dentro de when .

Ejemplo

try
{ 
  // ...
}
catch (Exception e) when (e.InnerException != null) // Any condition can go in here.
{
  // ...
}

La misma información se puede encontrar en las características de C # 6.0 aquí: Filtros de excepción

Recorriendo una excepción dentro de un bloque catch

Dentro de un bloque catch , la palabra clave throw se puede usar sola, sin especificar un valor de excepción, para volver a emitir la excepción que se acaba de capturar. La repetición de una excepción permite que la excepción original continúe en la cadena de manejo de excepciones, preservando su pila de llamadas o datos asociados:

try {...}
catch (Exception ex) {
  // Note: the ex variable is *not* used
  throw;
}

Un antipatrón común es throw ex , que tiene el efecto de limitar la siguiente vista del controlador de excepción de la traza de pila:

try {...}
catch (Exception ex) {
  // Note: the ex variable is thrown
  //  future stack traces of the exception will not see prior calls
  throw ex;  
}

En general, no es deseable utilizar la función throw ex , ya que los futuros controladores de excepciones que inspeccionan el seguimiento de la pila solo podrán ver las llamadas tan atrás como la throw ex . Al omitir la variable ex , y al usar solo la palabra clave throw , la excepción original se "disparará" .

Lanzar una excepción a partir de un método diferente y preservar su información.

Ocasionalmente, querría atrapar una excepción y lanzarla desde un hilo o método diferente mientras se conserva la pila de excepciones original. Esto se puede hacer con ExceptionDispatchInfo :

using System.Runtime.ExceptionServices;

void Main()
{
    ExceptionDispatchInfo capturedException = null;
    try
    {
        throw new Exception();
    }
    catch (Exception ex)
    {
        capturedException = ExceptionDispatchInfo.Capture(ex);
    }
    
    Foo(capturedException);
}

void Foo(ExceptionDispatchInfo exceptionDispatchInfo)
{
    // Do stuff

    if (capturedException != null)
    {
        // Exception stack trace will show it was thrown from Main() and not from Foo()
        exceptionDispatchInfo.Throw();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow