.net 有没有可能;“返回两次”;从嵌套函数开始?
我有一个函数(表单中的事件处理程序),其结构如下:.net 有没有可能;“返回两次”;从嵌套函数开始?,.net,vb.net,winforms,goto,.net,Vb.net,Winforms,Goto,我有一个函数(表单中的事件处理程序),其结构如下: 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(
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
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
我注意到大部分代码都是simular结构,所以我尝试如下重构:
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
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
但是它不起作用,因为我需要“返回两次”,而不仅仅是从嵌套函数返回!使用goto也不起作用,因为现有标签超出了嵌套函数的范围
在.net中有这样做的方法吗?我知道可以从HandleError返回布尔值并在其上进行分支,但它会再次返回到相同的重复结构。如果修改方法以引发异常而不是返回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.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
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
Dim errMsg as String=“”
CheckIfValidUser(…,errMsg)
如果errMsg=“”,则CheckIfBookAvailable(…,errMsg)
如果errMsg=“”,则ReserveBook(…,errMsg)
如果errMsg“”则
淋浴错误(错误消息)
日志错误(errMsg)
返回
如果结束
BookReserved=True
就我个人而言,我更喜欢第一种选择,因为这比现在在.NET中做事情的方式更惯用。不必将业务逻辑与技术错误处理细节结合在一起,这正是异常如此强大的原因。处理异常的一个选项是将
Check
subs重写为返回布尔值的函数(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风格…这是一种非常古老的编码风格。一种更现代的样式是,让每个执行验证的函数在出现问题时抛出异常,然后(通常尽可能高)有一个异常处理程序来捕获这些异常,显示消息并记录它们。@Damien_不信者哦,我没有注意到这是一种旧样式;我只是发现这样写的时候,流程是显而易见的。因为抛出异常对我来说有点模棱两可:你不能仅仅通过查看调用就知道哪个函数会/不会抛出异常(以及哪些异常)!同样,您也不能仅通过查看此代码就知道哪些情况会导致
errMsg
任何这些方法的长度为非零。一般来说,好的文档对于治愈这两种疾病都有很大的帮助。而且,至少在例外情况下,您不能忘记检查errMsg
。仔细想想,它实际上看起来很整洁。但是,如果某些需要在上释放资源的方法失败了怎么办?(例如,如果CheckIfBookAvailable失败,则注销图书检查系统)嵌套的try/catch?@jack3694078:这就是try…Finally
的目的(因为您通常希望在成功后以及失败后都注销图书检查系统)。事实并非如此。预订图书后,用户需要输入更多信息(地址等),然后才能订购ReservedBook()并注销。这是另一种功能(事实上是另一种形式)。@jack3694078:我明白了,这是有道理的。在这种情况下,我仍然会使用一个内部Try…Finally
块,但在Finally块中执行类似的操作,如果没有BookReserved,则注销。