尝试/捕捉每个班级的每一种方法?

ekk*_*kis 4 c# exception-handling

当我们在try/catch中包含一堆语句并且其中一个发出异常时,在catch中我们无法知道哪个语句导致了异常(ex.stacktrace显示了我们当前的方法(doit))调用者,调用者的调用者等,但不是do1或do2):

function doit() {
   try {
     do1();
     do2();
     [...]
   }
   catch (Exception ex) {
     // what failed?
   }
}
Run Code Online (Sandbox Code Playgroud)

一般来说,我已采取包装所有陈述和重新抛出,有点像:

private void do1() {
  try {
     // do whatever
  } catch(Exception e) {
     // write to my error log
     throw new Exception("do1: " + e.Message, e.InnerException);
  }
}
Run Code Online (Sandbox Code Playgroud)

这会在我的日志中留下痕迹,并使链条可用于上游.当然,问题是我必须用这种代码包装我写的每个方法.

有些东西告诉我,我对此很愚蠢.什么是正确的方法?

M.S*_*amm 8

好吧,这很难做到正确,因为异常处理是一个非常敏感的主题,在过去,人们已经就如何正确行事进行了宗教战争.

首先:既不使用空的catch(try { ... } catch { ... }),也不使用catch(Exception ex).Exception派生类的唯一目的是为您提供有关发生的异常类型的丰富信息,以便您可以在异常处理程序中执行有意义的操作(如果线程崩溃重新启动它,如果数据库连接失败,则非永久性地再次尝试,然后失败等).

人们倾向于使用catch-all处理程序来处理代码的最外层部分以记录未捕获的异常,这是好的,但无论如何你应该提示用户或重新抛出异常(使用throw,不是throw ex- 有一吨关于这一点的讨论).

基本上,您没有以编程方式关心异常发生的位置.您可以处理它,也可以不处理它.如果你无法处理它,那么你就无法抓住它.

附录:最重要的原因是"如果你可以做些什么,就这样做,否则你不敢触摸那个例外"的哲学是,默默地捕获异常(无论是否记录)都会导致真正难以发现的错误.将它们推送到日志文件可能是不够的,因为在实时系统中,您可能无法获得完全注释的堆栈跟踪(带有行号和所有内容).

附录2:例如,需要整数输入的文本框.如果用户提供的字符串无法有效处理输入,则可能会抛出转换异常,捕获该特定异常并将文本框重置为其旧值,并可能通知用户错误输入.或者,您的程序可能只是因为异常而死(设计不好,您可以从该异常中恢复)或者静默继续显示错误输入,但仍然使用旧值(设计错误,程序误导).

  • 我不同意Exception ex.在系统中有一些点,您希望捕获任何异常,因此它不会在堆栈中向上移动.这方面的一个例子就是你的应用程序启动课程.捕获未处理的异常,记录它,向用户显示消息,然后正常处理而不是崩溃应用程序. (2认同)

Bri*_*haw 4

如果您确实愿意这样做(其他人已经说明了为什么这很糟糕),请使用面向方面的编程方法。这将使您的生活变得更加轻松,并减少您最终编写和维护的代码量。

看一下PostSharp,它为您提供了一个框架,允许您使用将为您生成此样板错误处理的属性来装饰方法、类或命名空间。