2011-02-06 50 views
20

¿Hay una mejor manera de hacer caso omiso de una excepción en C# de ponerlo en un bloque intento de captura y no hacer nada en la captura? Encuentro que esta sintaxis es engorrosa. Para un bloque de código, ¿no puedo simplemente "etiquetarlo" de tal manera que el tiempo de ejecución sepa qué excepciones descuidar?Ignorar excepciones en C#

+1

que conozco haciendo caso omiso de excepciones es una mala práctica de programación, pero mi pregunta no es eso. No veo un punto en tener un bloque de catch vacío, de ahí la pregunta. –

Respuesta

23

No creo que hay un truco para evitar la excepción, pero se puede utilizar el siguiente fragmento de código:

public void IgnoreExceptions(Action act) 
{ 
    try 
    { 
     act.Invoke(); 
    } 
    catch { } 
} 

Utilizando el método se parece a:

IgnoreExceptions(() => foo()); 

Otra solución es utilizar AOP (Programación Orientada a Aspectos) - hay una herramienta llamada PostSharp que le permite crear un atributo que capturaría todas las excepciones en un ensamblaje/clase/método específico, que está más cerca de lo que está buscando.

+8

* @ Dror *, buena idea. Sin embargo, tenga en cuenta que su código contiene un error sutil: CLR realmente permite arrojar * cualquier * valor, no solo objetos de tipo 'Excepción' (esta restricción solo se aplica mediante C#). Por lo tanto, debe volver a escribir su bloque 'catch' como simplemente: **' catch {} '**; de lo contrario, ciertas excepciones inusuales en realidad podrían volver a la persona que llama! - Ver p. [este artículo del blog] (http://blogs.msdn.com/b/shawnfa/archive/0001/01/01/400749.aspx) (aproximadamente dos páginas abajo) para referencia. – stakx

+0

(Lo arreglé ahora. Aproveché la ocasión cuando detecté otro error tipográfico en tu código, que también he corregido. Espero que no te importe.) – stakx

+1

En lugar de actuar. Invocar(), ¿por qué no utilizarlo? acto()? –

1

No. Cuando se producen excepciones, viajan de vuelta hacia arriba en la pila de llamadas hasta que son manejadas por un bloque catch o todo el proceso finaliza.

5

Puede hacerlo con AOP. Postsharp, por ejemplo, le permitirá implementar fácilmente dicho atributo, que omitirá excepciones particulares en los métodos a los que haya aplicado dicho atributo. Sin AOP no veo una buena manera de hacerlo (si suponemos que hay una buena manera de hacer tales cosas;)).

Con PostSharp usted será capaz de decorar sus métodos de esta manera:

[IgnoreExceptions(typeof(NullReferenceException), typeof(StackOverflowException))] 
void MyMethod() { ... } 
3

Una forma es tomar advantge de programación orientada a aspectos (AOP). Eche un vistazo al PostSharp. Here es un ejemplo del uso de un atributo de excepción en un método, de modo que si ocurre una excepción, puede tratarlo sin un bloque try..catch.

EDIT:

Ah sí, la sugerencia de Dror es también un buen año. He visto ejemplos de eso en la Biblioteca Enterprise. Eso sería mejor si no desea tener un marco de terceros en su proyecto (es decir, PostSharp).

2

Yo no conozco a ningún mecanismo que permita que hagas esto.

En general, también se considera una muy mala práctica de ignorar excepciones. Las excepciones son (o siempre deben ser) planteadas por una buena razón; si nada más, al menos deberías registrarlos.

Si sabe que un cierto tipo de excepción no es crítico para su aplicación, puede evitar que se bloquee utilizando el evento Application.UnhandledException, buscando ese tipo de excepción. Tenga en cuenta que esto aún propagará la excepción a través de todos los cuadros de pila hasta el final.

0

No. Si se produce una excepción, por lo general es un error crítico que ha acaecer. No quieres ignorarlo.

su lugar debe reescribir su código para comprobar los errores y sólo si realmente falla, una excepción es fundido.

Por ejemplo, usando Int32.TryParse en lugar de Int32.Parse para comprobar si un objeto es un número entero válido. Recuerde que las excepciones son muy costosas cuando se lanzan y muchas versiones afectan seriamente el rendimiento de su aplicación.

+2

Jon skeet quote: "Si alguna vez llega al punto en que las excepciones perjudican significativamente su rendimiento, tiene problemas en términos de uso de excepciones más allá del rendimiento". http://www.yoda.arachsys.com/csharp/exceptions2.html –

0

Los bloques de captura vacíos son un olor a código muy apestoso.En resumen, no debería seguir una forma taquigráfica de escribirlos.

La regla n. ° 1 es: "no la atrape si no puede manejarla". La regla n. ° 1a es, "si no manejó la Excepción, vuelva a tirarla".

Si solo intenta evitar que la aplicación se bloquee, existen mecanismos más apropiados para usar en la mayoría de los casos. .NET incluye eventos UnhandledException en los niveles de Application, Dispatcher y AppDomain, así como eventos dedicados a notificarle de excepciones no controladas en hilos de fondo. En este nivel, si no puede verificar el estado de su aplicación, su mejor opción puede ser notificar al usuario que algo malo sucedió y finalizar la aplicación.

+0

Comer una excepción es manejar la excepción. Por ejemplo, no desearía que su marco de registro arrojara excepciones que impidan el funcionamiento de su negocio. Básicamente, no desea que su tarea principal falle solo porque puede haber un problema en el código opcional no esencial. La regla n. ° 1 debería ser no hacer ninguna regla, porque todo depende. Siempre necesita comprender por qué hace algo y qué implicaciones tiene. Además, ¿de qué manera tu respuesta aporta claridad a la pregunta original? – NoOneSpecial

0

Quería contribuir con los métodos de extensión que creé en base a las respuestas anteriores. Espero que ayude a alguien.

/// <summary> 
/// Extension methods for <see cref="Action"/> objects. 
/// </summary> 
public static class ActionExtensions 
{ 
    /// <summary> 
    /// Executes the <paramref name="action"/> and ignores any exceptions. 
    /// </summary> 
    /// <remarks> 
    /// This should be used in very rare cases. 
    /// </remarks> 
    /// <param name="action">The action to execute.</param> 
    public static void IgnoreExceptions(this Action action) 
    { 
     try { action(); } 
     catch { } 
    } 

    /// <summary> 
    /// Extends an existing <see cref="Action"/> so that it will ignore exceptions when executed. 
    /// </summary> 
    /// <param name="action">The action to extend.</param> 
    /// <returns>A new Action that will ignore exceptions when executed.</returns> 
    public static Action AddIgnoreExceptions(this Action action) 
    { 
     return() => action.IgnoreExceptions(); 
    } 
} 

y la unidad de pruebas:

[TestClass] 
public class ActionExtensionsTests 
{ 
    [TestMethod] 
    public void IgnoreException() 
    { 
     Action justThrow =() => { throw new InvalidOperationException(); }; 
     justThrow.IgnoreExceptions(); 
    } 
    [TestMethod] 
    public void AddIgnoreException() 
    { 
     Action justThrow =() => { throw new InvalidOperationException(); }; 
     var newAction = justThrow.AddIgnoreExceptions(); 
     newAction(); 
    } 
} 
0
public static void Ignore<T>(Action a) where T : Exception 
    { 
     try 
     { 
      a(); 
     } 
     catch (T) 
     { 
     } 
    } 

de usar:

Ignore<InvalidOperationException>(() => foo());