【问题标题】:Is there a way I can avoid using GoTo in this situation?有没有办法避免在这种情况下使用 GoTo?
【发布时间】:2015-02-18 09:59:33
【问题描述】:

所以我有一个子程序(由命令按钮触发),它运行一个看起来相当耗时的进程(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

【问题讨论】:

    标签: vba ms-access goto


    【解决方案1】:

    GoTo 可以通过使用 do-while 块(它具有错误条件并且只运行一次)并在您想要跳过其余代码的任何地方使用“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 还允许您做一些非常奇怪/丑陋的事情,例如跳出范围而不实际超出范围。使用 do-while 可以确保代码的流畅性,同时保持代码的健全性和可读性。

    【讨论】:

    • 就结构和程序流程而言,此代码与我给出的示例非常相似,只是语法不同。考虑到这一点,如果您可以添加一些关于为什么语法更改是有益的细节,这将是一个更好的答案,它避免了哪些陷阱,我可能会遇到GoTo
    • GoTo 必须非常谨慎地使用,因为它可能会使代码在代码中的一些迭代之后变得非常复杂。同样使用 GoTo,它允许您做非常奇怪/丑陋的事情,例如跳出范围而不实际超出范围等。使用 Do 循环,您可以确保代码的流动,保持代码的健全性和可读性.
    • 有很好的理由,但最好将更多信息编辑到您的答案中,而不是仅仅将其作为评论 :)
    【解决方案2】:

    引发自定义错误可以避免对具有这种错误处理结构的子例程使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-23
      相关资源
      最近更新 更多