如何摆脱尝试捕获?

时间:2008-11-11 06:01:54

标签: c# error-handling

我对周围的代码感到无聊,尝试像这样抓住..

try
{
    //some boring stuff
}
catch(Exception ex)
{
    //something even more boring stuff
}

我想要像

这样的东西
SurroundWithTryCatch(MyMethod)

我知道我可以通过创建具有该函数的确切签名的委托来完成此行为,但是为我的应用程序中的所有方法创建委托它不是一个选项。

我也可以通过注入IL代码来实现这一点,但这在性能方面很昂贵,因为它会在我的周围创建一个包装器组件。

还有其他有效的想法吗?

7 个答案:

答案 0 :(得分:23)

首先,听起来你可能经常使用try / catch - 特别是如果你正在捕捉Exception。 try / catch块应该比较少见;除非你能真正“处理”异常,否则你应该让它冒泡到堆栈的下一层。

现在,假设你真的想要所有这些try / catch块,为什么它不是创建委托的选项?使用匿名方法和lambda表达式,以及System命名空间中的Func / Action委托,基本上很少有工作要做。你写道:

public void SurroundWithTryCatch(Action action)
{
    try
    {
        action();
    }
    catch(Exception ex)
    {
        //something even more boring stuff
    }    
}

然后你的SurroundWithTryCatch(MyMethod)可以正常工作,如果它不需要参数。

或者,如果您不想调用不同的方法,请写下:

public void MyMethod()
{
    SurroundWithTryCatch(() => 
    {
        // Logic here
    });
}

如果您需要从该方法返回,您可以执行以下操作:

public int MyMethod()
{
    return SurroundWithTryCatch(() => 
    {
        // Logic here
        return 5;
    });
}

具有SurroundWithTryCatch的泛型重载,如下所示:

public T SurroundWithTryCatch<T>(Func<T> func)
{    
    try
    {
        return func();
    }
    catch(Exception ex)
    {
        //something even more boring stuff
    }    
}

大部分内容在C#2中也没问题,但是类型推断对你的帮助不大,你必须使用匿名方法而不是lambda表达式。

回到开头:尽量少用try / catch。 (尝试/最后应该更频繁,尽管通常写为使用声明。)

答案 1 :(得分:4)

面向方面编程也可以帮助您,但这可能需要您向项目添加库,postsharp在这种情况下会帮助您。 请参阅此链接http://doc.postsharp.org/1.0/index.html#http://doc.postsharp.org/1.0/UserGuide/Laos/AspectKinds/OnExceptionAspect.html#idHelpTOCNode650988000

答案 2 :(得分:3)

您可以尝试使用一些空验证。我可以采用LINQ to SQL示例:

var user = db.Users.SingleOrDefault(u => u.Username == 3);

if (user == null)
    throw new ArgumentNullException("User", "User cannot be null.");

// "else" continue your code...

答案 3 :(得分:2)

也许您通过不同的语法将异常处理视为错误代码?所以不要尝试/捕获。让异常向上传播。

答案 4 :(得分:2)

对我来说,我看起来像是在要求面向方面的编程。我想你应该看看PostSharp。

答案 5 :(得分:0)

我不确定C#,但是在Java-land中你可以定义并与所有方法接口,然后将它隐藏在代理对象下。你可以通过定义类似的东西来编写更多的代码来逃避:

ExceptionCatcher.catchAll(new Runnable() {
  public void run() {
     //run delegate here
     MyMethod();
  }
});

和catchAll()将只调用runnable并在其周围包装一个try-catch块。

但是,我认为你真正想要的是一种很好的语言closure support。使用闭包,做你想做的事非常容易。

答案 6 :(得分:0)

如果您使用的是Java,那么您就拥有RuntimeExceptions,这些异常意味着您无法从中恢复出错。仔细看看。从这里开始:http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html

例如,当出现问题时,Spring的数据访问位会抛出各种RuntimeExceptions。处理它们是可选的。