我有一个函数(表单中的事件处理程序)结构如下:
Dim errMsg as String = ""
CheckIfValidUser(..., errMsg)
If errMsg.Length > 0 Then
ShowError(errMsg)
LogError(errMsg)
Return
End If
CheckIfBookAvailable(..., errMsg)
If errMsg.Length > 0 Then
ShowError(errMsg)
LogError(errMsg)
Return
End If
ReserveBook(..., errMsg)
If errMsg.Length > 0 Then
ShowError(errMsg)
LogError(errMsg)
Return
End If
BookReserved = True
我注意到大部分代码都是类似的结构,所以我尝试重构如下:
Dim errMsg as String = ""
Dim HandleError = Sub()
If errMsg.Length > 0 Then
ShowError(errMsg)
LogError(errMsg)
Return
End If
End Sub
CheckIfValidUser(..., errMsg)
HandleError()
CheckIfBookAvailable(..., errMsg)
HandleError()
ReserveBook(..., errMsg)
HandleError()
BookReserved = True
但它不会起作用,因为我需要"两次返回"而不只是从嵌套函数返回!使用goto不起作用,因为exiting标签超出了嵌套函数的范围。
无论如何在.net中执行此操作?我知道可以从HandleError返回一个布尔值并对其进行分支,但它会再次返回到相同的重复结构。
答案 0 :(得分:7)
如果您修改方法以抛出异常而不是返回ByRef错误消息,则可以按如下方式重写代码:
Try
CheckIfValidUser(...)
CheckIfBookAvailable(...)
ReserveBook(...)
BookReserved = True
Catch ex As Exception
ShowError(ex.Message)
LogError(ex.Message)
End Try
通常,捕获所有异常(" Pokemon异常处理")被认为是不好的做法,除非在最外层(即用户界面)进行此操作。由于您显示错误消息(并且因为您提到这是表单中的事件处理程序),所以这似乎就是这种情况。
如果您无法更改方法的结构,则另一个选项如下:
Dim errMsg as String = ""
CheckIfValidUser(..., errMsg)
If errMsg = "" Then CheckIfBookAvailable(..., errMsg)
If errMsg = "" Then ReserveBook(..., errMsg)
If errMsg <> "" Then
ShowError(errMsg)
LogError(errMsg)
Return
End If
BookReserved = True
就个人而言,我更喜欢第一种选择,因为现在用.NET完成的方式更为惯用。不必将业务逻辑与技术错误处理细节进行集群,完全是什么使异常变得如此强大。
答案 1 :(得分:2)
处理异常的一个选项可以是将Check
个子重写为返回布尔值的函数(true
成功,false
如果errMsg
包含错误)并且有一个每个调用下一个函数的IF
个表达式的级联。最后有一条错误处理代码
If CheckIfValidUser(..., errMsg) Then
if CheckIfBookAvailable(..., errMsg) then
ReserveBook(..., errMsg)
End If
End If
If errMsg.Length > 0 Then
ShowError(errMsg)
LogError(errMsg)
Return
End If
BookReserved = True
但我同意这是旧时代C风格......