有什么办法可以避免在这种情况下使用 GoTo 吗?

Is there a way I can avoid using GoTo in this situation?

所以我有一个子程序(由命令按钮触发),它运行一个看起来非常耗时的过程(5 到 20 秒之间,取决于机器以及我们的网络感觉如何合作) .为了让用户清楚他们看不到的事情正在发生,我将鼠标指针更改为沙漏,然后在子程序退出时将其更改回沙漏,无论退出的原因如何。

考虑到这一点,我的代码看起来像这样(说明性示例,不是实际代码):

Private Sub cmdDoTheThing_Click()
On Error GoTo Err_cmdDoTheThing

    Screen.MousePointer = 11 'Hourglass/Equivalent

    'Check all data is available to Do The Thing
    If Not MyModule.ThingIsDoable(Me.PrimaryKey) Then
        MsgBox "Cannot Do The Thing, more preliminary things must be done first."
        GoTo Exit_cmdDoTheThing
    End If

    'Try to Do The Thing (function returns false on failure)
    If Not MyModule.DoTheThing(Me.PrimaryKey) Then
        MsgBox "Processing of The Thing failed."
        GoTo Exit_cmdDoTheThing
    End If

    '...
    'Stuff here I don't want to do if either of the above failed
    '...

Exit_cmdDoTheThing:
    Screen.MousePointer = 0 'Default mouse pointer
    Exit Sub

Err_cmdDoTheThing:
    MsgBox "Error " & Err.Number & ": " & Err.Description
    Resume Exit_DoTheThing
End Sub

我不想在每个可能的退出点重复 Screen.MousePointer = 0,所以我认为 GoTo 可以作为一个不错的快捷方式,因为无论如何都需要 Exit_cmdDoTheThing 标签来进行错误处理。

这是 GoTo 语句的有效用例吗?如果不是,是否有其他方法可以达到相同的结果?毕竟不想突然raptor attack

GoTo 可以通过使用一个 do-while 块(它有一个 false 条件并且只运行一次)和使用 'Exit Do' 来替换你想跳过其余代码的任何地方。

因此您的代码现在可能如下所示:

Private Sub cmdDoTheThing_Click()
On Error GoTo Err_cmdDoTheThing

    Do
        Screen.MousePointer = 11 'Hourglass/Equivalent

        'Check all data is available to Do The Thing
        If Not MyModule.ThingIsDoable(Me.PrimaryKey) Then
            MsgBox "Cannot Do The Thing, more preliminary things must be done first."
            Exit Do
        End If

        'Try to Do The Thing (function returns false on failure)
        If Not MyModule.DoTheThing(Me.PrimaryKey) Then
            MsgBox "Processing of The Thing failed."
            Exit Do
        End If

        '...
        'Stuff here I don't want to do if either of the above failed
        '...
    Loop While FALSE

Exit_cmdDoTheThing:
    Screen.MousePointer = 0 'Default mouse pointer
    Exit Sub

Err_cmdDoTheThing:
    MsgBox "Error " & Err.Number & ": " & Err.Description
    Resume Exit_DoTheThing
End Sub

必须非常小心地使用 GoTo,因为在代码中进行一些迭代后,它可能会使代码变得非常复杂。 GoTo 还允许您做非常 weird/ugly 的事情,例如跳出范围而不实际超出范围。使用 do-while 可以确保代码的流动,同时保持代码的完整性和可读性。

引发自定义错误可以避免将 GoTo 用于具有此错误处理结构的子例程。这有一个额外的好处,就是让任何阅读代码的人都清楚,在这种情况下,某些功能未能完成被认为是错误,即使他们在失败时没有引发错误。

Public Const cCustomErrNum = 9114

Private Sub cmdDoTheThing_Click()
On Error GoTo Err_cmdDoTheThing

    Screen.MousePointer = 11 'Hourglass/Equivalent

    'Check all data is available to Do The Thing
    If Not MyModule.ThingIsDoable(Me.PrimaryKey) Then
        Err.Raise cCustomErrNum,"cmd_DoTheThing_Click()", _
            "Cannot Do The Thing, more preliminary things must be done first."
    End If

    'Try to Do The Thing (function returns false on failure)
    If Not MyModule.DoTheThing(Me.PrimaryKey) Then
        Err.Raise cCustomErrNum,"cmd_DoTheThing_Click()", _
            "Processing of The Thing failed."
    End If

    '...
    'Stuff here I don't want to do if either of the above failed
    '...

Exit_cmdDoTheThing:
    Screen.MousePointer = 0 'Default mouse pointer
    Exit Sub

Err_cmdDoTheThing:
    MsgBox "Error " & Err.Number & ": " & Err.Description
    Resume Exit_DoTheThing
End Sub