这里有两种截然不同的思想流派,两者的支持者常常对任何人都可能相信另一种方式感到震惊和惊讶。最后,这是一个偏好问题,以及您的目标用户群期望和/或愿意接受什么,更重要的是,您对应用程序功能的了解程度如何。 (你的问题暗示你没有编写所有涉及的代码,所以最后一点可能比你想象的要棘手。)
首先,我假设您在这里谈论的是最终用户应用程序,而不是类库。几乎没有充分的理由在您没有明确处理的类库中捕获异常。你总是把决定权留给来电者。
但是,在最终用户应用程序中,最终决定权在您手中,因为调用链上没有任何人。在这种情况下,您有两个广泛的选择:
快速失败
有些人认为,当遇到错误时,最好让应用程序在物理上尽快崩溃。虽然这似乎有点适得其反,但请记住遇到未处理的异常意味着什么:您实际上不知道出了什么问题;即使是像您的错误日志代码这样简单的事情也可能以您意想不到的方式运行。
如果您在调用站点正确处理异常,则只有在发生非常非常糟糕的事情时才会收到这种“意外”错误:内存不足、堆栈损坏等。那种事情你不能无论如何,真的要从中恢复过来,所以尝试没有意义。
优雅地失败
其他人认为,您应该尽可能隔离错误,以防止您的用户丢失信息。如果您的应用程序足够模块化,那么一个区域的完全故障可能对另一区域的数据完全没有影响。
这是一个风险更大的提议:您必须非常小心,不要让自己处于不一致的状态。它要求您确定地知道,失败代码中的任何内容都不会从代码的其他部分更改状态。
结论
像往常一样,“正确”的答案可能在中间的某个地方。一般来说,在不一致的状态下运行的风险几乎总是让应用程序死掉的好理由。当然,您可能仍希望在此处进行某种程度的日志记录,您可以通过多种方式完成。我的偏好不是为此使用异常,而是挂钩到顶级的各种“未处理异常”事件,例如this、this 或this。在这些事件处理程序中记录您的异常,可能会显示一个“更友好”的错误对话框,然后让您的应用程序关闭。例如,我们在我们生成的 WPF 应用程序中放置了类似的内容:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DispatcherUnhandledException="UnhandledException">
private void UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
logger.FatalException("OH NOES! Bad stuff happened, bailing out.", e.Exception);
MessageBox.Show("holy cow something bad happened:\r\n" + e.Exception.Message);
}
但是,在某些地方捕获所有异常可能是安全的;这主要限于无论如何都会丢弃所有数据的地方。例如,打印或导出已完成操作的结果可能会“安全地”失败,而不会对应用程序的其余部分产生不良影响。您可能不希望您的应用程序因为用户没有打印机而崩溃。 (我什至遇到过一个第三方打印库的案例,它在错误中明确抛出System.Exception...)但是您必须非常小心,您知道自己在做什么,并且您的数据是真正隔离的来自系统的其余部分。