2011-02-06 116 views
20

有没有更好的方法来忽略C#中的异常,而不是将它放在try catch块中,并在catch中无作为?我觉得这个语法很麻烦。对于代码块,我不能简单地以这种方式“标记”它,以便运行时知道要忽略哪些异常?在C中忽略异常#

+1

我知道忽略异常是一个不好的编程习惯,但我的问题是不是。我没有看到有一个空的catch块,因此这个问题。 – 2011-02-07 15:07:28

回答

23

我不认为有一个小窍门,以避免异常,但你可以用下面的代码片段:

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

使用方法是这样的:

IgnoreExceptions(() => foo()); 

另一种解决方案是使用AOP(面向方面​​的编程) - 有一个名为PostSharp的工具,它使您能够创建一个属性,可以捕获特定程序集/类/方法中的所有异常,这更接近您要查找的内容。

+8

* @ Dror *,好主意。但是,请注意,您的代码包含一个微妙的错误:CLR实际上允许抛出任何*值,而不仅仅是Exception类型的对象(此限制仅由C#强制执行)。所以,你应该简单地重写你的`catch`块:**`catch {}`**;否则,某些异常的异常实际上可能会返回给调用者! - 见例如[本博客文章](http://blogs.msdn.com/b/shawnfa/archive/0001/01/01/400749.aspx)(约两页下)供参考。 – stakx 2011-02-06 12:16:56

+0

(我现在已经修复了,当我发现你的代码中有另一个错误的时候,我也纠正了错误,我希望你不要介意) – stakx 2011-02-06 12:27:21

+1

而不是act.Invoke(),为什么不使用法案()? – 2015-06-22 18:57:39

1

否。当出现exceptios时,它们会返回调用堆栈,直到它们由catch块处理或者整个过程终止。

5

您可以使用AOP来完成。例如Postharp将允许您轻松实现这样一个属性,该属性将跳过应用此类属性的方法中的特定异常。如果没有AOP,我认为没有什么好的方法可以做到这一点(如果我们假设有一种很好的方法来做这样的事情))。

随着Postsharp你将能够装点这样的方法:

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

一种方法是采取面向方面编程(AOP)的advantge。看看PostSharpHere是在方法上使用异常属性的示例,因此如果发生异常,则可以在try..catch块处理它。

编辑:

是啊,德罗尔的建议也是一个很好的一个。我在企业库中看到过这方面的例子。如果你不想在你的项目中使用第三方框架(比如PostSharp),那会更好。

2

我不知道任何机制,可以让你这样做。

通常,忽略异常也被认为是一种非常糟糕的做法。例外情况是(或应该总是)有充分的理由提出;如果没有别的,你至少应该记录它们。

如果您知道某种类型的异常对您的应用程序不是至关重要的,可以使用Application.UnhandledException事件来防止它崩溃,检查是否有这种异常。请注意,这仍将通过所有堆栈帧将异常传播到最底层。

0

不。如果抛出异常,通常会发生严重错误。你不想忽视它。

相反,您应该重写您的代码来检查错误,并且只有在确实失败时才会抛出异常。

例如使用Int32.TryParse而不是Int32.Parse来检查对象是否为有效整数。请记住,异常在投射时非常昂贵,而且许多投射会严重影响应用程序的性能。

0

空的catch块是非常臭的代码气味。总之,你不应该追求写他们的速记方式。

规则1是,“如果你不能处理它,不要抓住它。” 规则#1a是“如果你实际上没有处理异常,请重新抛出异常。”

如果您只是试图阻止应用程序崩溃,那么在大多数情况下可以使用更合适的机制。 .NET包括Application,Dispatcher和AppDomain级别的UnhandledException事件,以及专门用于通知您后台线程上未处理的异常的事件。在这个级别上,如果你无法验证你的应用程序的状态,最好的选择可能是通知用户发生了不好的事情并终止应用程序。

0

我想根据以前的答案提供我创建的扩展方法。希望它能帮助别人。

/// <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(); 
    } 
} 

而且单元测试:

[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) 
     { 
     } 
    } 

要使用:

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