删除过多的try-catch块

我正在重构由其他开发人员编写的中型WinForms应用程序,并且几乎每个类的每个方法都被try-catch块包围。 99%的时间这些catch只阻止记录exception或清理资源并返回错误状态。

我认为很明显,这个应用程序缺乏适当的exception处理机制,我打算删除大多数try-catch块。

这样做有什么不利之处吗? 你会怎么做? 我打算:

  • 要适当地记录exception并阻止它们传播给用户,请使用Application.ThreadException处理程序

  • 对于需要清理资源的情况,请保留try-catch块

更新 :使用usingtry-finally块是一种更好的方法。 谢谢你的回复。

  • 在“return-false-on-error”的方法中,让exception传播并在调用者中捕获它

欢迎任何更正/建议。

编辑:在第3项中,“return-false-on-error”我的意思是这样的方法:

 bool MethodThatDoesSomething() { try { DoSomething(); // might throw IOException } catch(Exception e) { return false; } } 

我想把它重写为:

 void MethodThatDoesSomething() { DoSomething(); // might throw IOException } // try-catch in the caller instead of checking MethodThatDoesSomething's return value try { MethodThatDoesSomething() } catch(IOException e) { HandleException(e); } 

“要适当地记录exception并防止它们传播给用户,请使用Application.ThreadException处理程序”

那么你能告诉用户发生了什么吗? 所有例外都会在那里结束吗?

“对于有需要清理的资源的情况,请保留try-catch块”

如果您希望在其他地方处理exception,也可以使用try-finally块。 还要考虑在IDisposable资源上使用using关键字。

“在”return-false-on-error“的方法中,让exception传播并在调用者中捕获它”

这取决于方法。 只有在特殊情况下才会出现例外情况。 FileNotFoundException对于FileExists()方法来说很奇怪,但OpenFile()抛出完全合法。

对于清理,请使用try-finally或按照IDisposable建议实现IDisposable 。 对于在出错时返回bool的方法,请尝试并在不满足条件时返回false。 例。

 bool ReturnFalseExample() { try { if (1 == 2) thow new InvalidArgumentException("1"); }catch(Exception e) { //Log exception return false; } 

而是改为这个。

 bool ReturnFalseExample() { if (1 == 2) { //Log 1 != 2 return false; } 

如果我没有弄错, try catches是一个昂贵的过程,如果可能的话,你应该尝试确定是否满足条件,而不是只捕获exception。 }

作为“return-false-on-error”的选项,您可以通过以下方式清理代码:

  static class ErrorsHelper { public static bool ErrorToBool(Action action) { try { action(); return true; } catch (Exception ex) { LogException(ex); return false; } } private static void LogException(Exception ex) { throw new NotImplementedException(); } } 

和用法示例:

  static void Main(string[] args) { if (!ErrorToBool(Method)) { Console.WriteLine("failed"); } else if (!ErrorToBool(() => Method2(2))) { Console.WriteLine("failed"); } } static void Method() {} static void Method2(int agr) {} 

您应该处理您期望的exception,知道如何处理它们并且它们不会破坏您的应用程序的状态,否则让它们抛出。

一个好的方法是首先记录exception,然后重新启动应用程序,就像Microsoft在办公室或visual studio崩溃时所做的那样。 为此,您必须处理应用程序域无法处理的exception,因此:

 AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainUnhandledException; //Add these two lines if you are using winforms Application.ThreadException += OnApplicationThreadException; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); private void OnCurrentDomainUnhandledException(object sender, System.Threading.ThreadExceptionEventArgs e) { //Log error //RestartTheApplication } 

这是一个如何重新启动应用程序的示例。

我认为你的删除try / catch块的策略似乎只是做了一般的无思路日志记录。 显然需要保留清理代码。 但是,我认为第三点需要进一步澄清。

对于exception不可避免的事情,错误方法返回false通常是正常的,例如示例中的文件操作。 虽然我可以看到删除exception处理代码的好处,但是我会仔细考虑通过在调用链中推动处理此类exception的责任而获得的好处。

如果该方法正在做一些非常具体的事情(它不是通用的框架代码),并且您知道哪些调用者正在使用它,那么我会让它吞下exception,让调用者免于exception处理任务。 但是,如果它是更通用的东西,也许更多的是框架方法,你不确定将调用该方法的代码,我可能会让exception传播。

您可以尝试使用AOP。

例如,在AOP到PostSharp中,您可以在一个中心位置(一段代码)处理exception作为一个方面。

查看文档中的示例以获得一个想法=> 使用PostSharp进行exception处理的文档 。

最好的是其他人说的,在1个地方做exception处理。 隐藏被提升的例外而不是允许冒泡的不良做法。