我的异常处理策略是:
通过连接到应用程序来捕获所有未处理的异常。线程异常事件,然后决定:
对于UI应用程序:向用户弹出一个道歉消息(WinForms)
对于服务或控制台应用程序:将其记录到文件(服务或控制台)
然后我总是在try/catch中附上外部运行的每一段代码:
WinForms基础架构触发的所有事件(加载、单击、选定更改…)
由第三方组件触发的所有事件
然后加上try/catch
我所知道的所有操作可能并不总是有效(IO操作,潜在的零除法计算……)。在这种情况下,我抛出一个新的ApplicationException(“自定义消息”,innerException)来跟踪实际发生的事情
此外,我尽最大努力对异常进行正确排序。但也有例外:
需要立即显示给用户
当它们发生时,需要一些额外的处理来将它们放在一起,以避免级联问题(例如:在TreeView填充期间将. endenddate放在finally部分)
用户并不关心,但重要的是要知道发生了什么。所以我总是记录它们:
在事件日志中
或者在磁盘上的.log文件中
在应用程序顶级错误处理程序中设计一些静态方法来处理异常是一个很好的实践。
我还强迫自己试着:
记住,所有的异常都被冒泡到顶层。没有必要把异常处理程序放在任何地方。
可重用的或深度调用的函数不需要显示或记录异常:它们要么自动生成,要么在异常处理程序中使用一些自定义消息重新抛出。
最后:
Bad:
// DON'T DO THIS; ITS BAD
try
{
...
}
catch
{
// only air...
}
用处:
// DON'T DO THIS; IT'S USELESS
try
{
...
}
catch(Exception ex)
{
throw ex;
}
have a try finally without a catch是完全正确的:
try
{
listView1.BeginUpdate();
// If an exception occurs in the following code, then the finally will be executed
// and the exception will be thrown
...
}
finally
{
// I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURRED OR NOT
listView1.EndUpdate();
}
我在顶层做的是:
// i.e When the user clicks on a button
try
{
...
}
catch(Exception ex)
{
ex.Log(); // Log exception
-- OR --
ex.Log().Display(); // Log exception, then show it to the user with apologies...
}
我在一些被调用的函数中所做的:
// Calculation module
try
{
...
}
catch(Exception ex)
{
// Add useful information to the exception
throw new ApplicationException("Something wrong happened in the calculation module:", ex);
}
// IO module
try
{
...
}
catch(Exception ex)
{
throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}
异常处理(自定义异常)有很多事情要做,但我试图记住的那些规则对于我做的简单应用程序已经足够了。
下面是一个扩展方法的例子,它以一种舒适的方式处理捕获的异常。它们以一种可以链接在一起的方式实现,并且非常容易添加您自己捕获的异常处理。
// Usage:
try
{
// boom
}
catch(Exception ex)
{
// Only log exception
ex.Log();
-- OR --
// Only display exception
ex.Display();
-- OR --
// Log, then display exception
ex.Log().Display();
-- OR --
// Add some user-friendly message to an exception
new ApplicationException("Unable to calculate !", ex).Log().Display();
}
// Extension methods
internal static Exception Log(this Exception ex)
{
File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
return ex;
}
internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
return ex;
}