是否可以从嵌套函数“返回两次”?

时间:2015-03-06 08:10:54

标签: .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(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返回一个布尔值并对其进行分支,但它会再次返回到相同的重复结构。

2 个答案:

答案 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风格......