是否可以从嵌套函数 "return twice" ?
Is it possible to "return twice" from nested function?
我有一个函数(表单中的事件处理程序)结构如下:
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
但这行不通,因为我需要 "return twice" 而不是仅从嵌套函数 returning!使用 goto 也不起作用,因为退出标签超出了嵌套函数的范围。
在 .net 中有没有办法做到这一点?我知道可以 return 来自 HandleError 的布尔值并在其上分支,但随后它再次返回到相同的重复结构。
如果您修改您的方法以引发异常而不是返回 ByRef 错误消息,您的代码可以重写如下:
Try
CheckIfValidUser(...)
CheckIfBookAvailable(...)
ReserveBook(...)
BookReserved = True
Catch ex As Exception
ShowError(ex.Message)
LogError(ex.Message)
End Try
通常,捕获 所有 异常 ("Pokemon Exception handling") 被认为是不好的做法,除非在最外层(即用户界面)执行此操作。由于您显示 一条错误消息(并且由于您提到这是表单中的事件处理程序),所以这里似乎就是这种情况。
如果您不能更改方法的结构,另一种选择是:
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 中完成事情的方式更为惯用的方式。不必将您的业务逻辑与技术错误处理细节聚集在一起正是异常如此强大的原因。
处理异常的一个选项是将您的 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 风格...
我有一个函数(表单中的事件处理程序)结构如下:
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
但这行不通,因为我需要 "return twice" 而不是仅从嵌套函数 returning!使用 goto 也不起作用,因为退出标签超出了嵌套函数的范围。
在 .net 中有没有办法做到这一点?我知道可以 return 来自 HandleError 的布尔值并在其上分支,但随后它再次返回到相同的重复结构。
如果您修改您的方法以引发异常而不是返回 ByRef 错误消息,您的代码可以重写如下:
Try
CheckIfValidUser(...)
CheckIfBookAvailable(...)
ReserveBook(...)
BookReserved = True
Catch ex As Exception
ShowError(ex.Message)
LogError(ex.Message)
End Try
通常,捕获 所有 异常 ("Pokemon Exception handling") 被认为是不好的做法,除非在最外层(即用户界面)执行此操作。由于您显示 一条错误消息(并且由于您提到这是表单中的事件处理程序),所以这里似乎就是这种情况。
如果您不能更改方法的结构,另一种选择是:
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 中完成事情的方式更为惯用的方式。不必将您的业务逻辑与技术错误处理细节聚集在一起正是异常如此强大的原因。
处理异常的一个选项是将您的 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 风格...