1

我已经开始大量使用异常,我相信我会从它中成长,因为我会通过艰苦的方式学习优缺点,但是在我成为异常大师之前,我想知道这种技术是否是可以接受的。

我打算在我自己的“SorryFailedToSaveYourData”异常中包装一个数据库异常,然后递归地移动显示消息的异常,有点像这样:

Try
    DoSomeWork
Catch
    BuildErrorMessage(lblError,ex)
End Try

Public Sub BuildErrorMessage(ByVal lbl As Label, ByVal ex As Exception)
    lbl.Text += "<br />" & ex.Message
    While Not ex.InnerException Is Nothing
        BuildErrorMessage(lbl, ex.InnerException)
    End While
End Sub

这种做法有用吗,还是在处理异常时我完全错过了这条船?我知道您可以创建自己的例外,但对于我们正在从事的项目的规模来说,这似乎有点矫枉过正。

谢谢

4

4 回答 4

2

ex.ToString() 将构建格式化的异常文本,您应该使用它而不是 .Message ,因为它可能无法为您提供调试所需的完整信息。

我还建议使用 AppendLine() 将字符串构建器传递给递归而不是标签,这样您还可以使用该文本发送电子邮件通知、编写事件查看器以及日志文件。为了在您的 UI 中显示(看起来您想要 html),只需将标签文本值设置为

StringBuilder.ToString().Replace(Environment.NewLine, "<br />")
于 2009-01-20T22:31:24.633 回答
2

我不会向您的应用程序用户显示每条内部异常消息。我会捕获真正的异常(即 SqlException)并将其作为您自己的异常重新抛出(即 throw new YouCantSaveThisTwiceException("This customer ID already exists") )。然后只需在漂亮的显示屏上向用户显示该手写信息即可。向自己发送一封包含完整堆栈跟踪的电子邮件/日志文件/等。

这有两个目的:

1)您可以看到真正的堆栈跟踪,这使您更容易找到并解决问题。

2) 不必向用户显示可怕的堆栈跟踪。相反,他们阅读了您写的一条好消息,让他们放心,尽管存在问题,但他们并没有“破坏”应用程序。

这适用于您不希望用户能够使用不同输入修复的异常。对于验证用户输入的异常,您通常可以在表示层中捕获这些异常,并在标签上将您的好消息显示给它们,而无需离开表单。

只有(仅!!!)如果您确切地知道您将要捕获什么并且您向用户提供有关如何修复它的明确说明,才使用此技术。否则,你最终会两全其美。用户不知道该怎么做,您也不会被告知存在错误。永远不要仅仅为了“捕获所有”异常而将整个方法包装在 try-catch 中。这种类型的处理应该在应用程序级别全局完成。

我在 Global.asax 中的 application_error 处理程序方法中执行所有全局异常处理(电子邮件、日志记录等)。您还可以创建一个处理应用程序错误的 HttpModule。然后,您可以从一个项目到另一个项目携带该功能。

于 2009-01-21T04:42:42.247 回答
0

您正在异常内部构建标签,大概是因为您想向用户显示消息。如果您的异常跨越应用程序的多个层(您提到包装自己的数据异常),那么这是一个糟糕的主意,因为它会违反封装并强制您的异常处理使用 UI 元素。

但是,通常,您不希望向用户显示错误消息。用户关心堆栈溢出发生了什么?他只关心应用程序是否损坏以及是否记录了错误报告并将其发送给相应的团队。

通常,当且仅当应用程序处于无法再运行的状态时,您才希望出现异常。如果它只是有条件地发生,您将希望使用条件显式处理它以检查它,而不是使用异常机制。

例如,如果您知道用户将在家中进行连接,并且您不能保证一定会有 Internet 连接,您可以检查 Internet 连接并显示一条消息说用户需要连接,而不是仅仅尝试使用 Internet连接并在不存在时创建异常。

于 2009-01-20T14:25:57.577 回答
0

编辑

我起初误读了您的问题,如果您向最终用户显示信息,您可能不想这样做。如果您要记录异常以便稍后排除故障,您将需要执行我的建议。

====

这是标准的,尽管我也会捕获堆栈跟踪和 Data 属性中的任何项目(尽管我没有看到任何框架代码使用这个你永远不知道的,如果你要抛出自己的异常或重新抛出异常,它很有用。

尽管您的实际代码中有错误,但您可能最终会陷入无限循环,因为您的外部异常将始终具有内部异常。

Public Sub BuildErrorMessage(ByVal lbl As Label, ByVal ex As Exception)   
 lbl.Text += "<br />" & ex.Message    
 If Not ex.InnerException Is Nothing     Then
    BuildErrorMessage(lbl, ex.InnerException)    
  End If 
End Sub
于 2009-01-20T14:27:16.077 回答