如何正确地从 Class 引发错误
How to Properly Raise Errors From Class
我的问题是:如何在 class 中正确引发错误,以便实例化 class 的调用者可以使用正确的错误处理技术?
我正在升级未使用 classes 的旧 VB6 意大利面条代码。过去我总是使用 On Error Resume Next 和 On Error Goto myLabel 用于在备选方案对我的代码没有任何清洁效果时处理错误。
但是,我无法让调用者处理错误,因为如果我在方法或 class 的 属性 中引发错误,无论我是否使用 On Error 语句从调用者那里捕获它。示例代码如下所示:
我的班级:
Public Sub Bar()
If valid Then
'some code here
Else
Err.Raise 5
End if
End Sub
主窗体:
Private Sub CallFoo()
Dim foo as New MyClass
On Error Goto fooliure 'Starts ignoring errors
Call foo.Bar() 'Program stops with an exception
On Error Goto 0 'Ends error handling
Exit Sub
fooliure:
'Error handling code
End Sub
Microsoft 还表示,这就是他们打算在 VB 6.0 中执行错误处理的方式,如前所述 here。
此时我正在考虑在我的 class 中使用一个对象来收集调用者可以检索的错误。如果我能避免那样做,我会的,但到目前为止我还没有找到答案。
David,这是关于 VBA 错误处理 101 的简短教程。
Err
对象。这是一个保存当前错误的单例对象。不要尝试实例化此对象(即不要使用 Set objErr = New Err
——这会失败)
On Error
- 设置错误处理。可能的错误处理程序:
On Error GoTo Label
- 遇到错误时执行跳转到Label
On Error Resume Next
- 执行遇到错误时跳转到下一行
On Error GoTo 0
- 关闭当前错误处理程序。任何后续错误将由调用者处理
On Error Resume
- 执行跳转到导致错误的行(不推荐)
Err
对象在以下情况下被清除(丢失当前错误):
- 子程序、函数或属性被调用
- 子程序、函数或属性正常退出
- 一个
On Error
语句被执行
Err.Clear
调用时清除当前错误
引发异常。您可以在需要时随时提出错误。规范形式:
Err.Raise 1001 + vbObjectError, Description:="An exception occurred."
- 自定义错误:使用
vbObjectError
来生成用户定义的错误。例子:
1001 + vbObjectError
- 整数范围是0到65535
- 错误处理顺序:
- 如果例程中定义了本地错误处理程序,则执行它
- 如果没有本地处理程序,则向调用者抛出错误
- 如果调用者没有处理程序,则不断引发错误,直到找到本地处理程序
- 如果没有顶级处理程序,应用程序终止
- 创建错误链。创建显示原始错误的错误链并在错误发生时显示堆栈上的例程列表非常有用。去做这个:
- 向每个 可能导致错误的例程添加错误处理
- 始终向调用者重新提出错误
- 在重新引发错误时将字符串添加到
Err.Source
命名例程
- 顶层调用例程可以使用
MsgBox
来通知用户错误(或者可以实现其他日志记录)
下面是演示这些想法的代码示例:
Public Sub TestErrorLevel1()
On Error GoTo HandleErr ' clears Err object
TestErrorLevel2
Exit Sub
HandleErr:
' top-level error handler -- nothing else to raise error to
' show error and complete call chain
MsgBox "Error: " & Err.Number & vbCrLf & Err.Description & vbCrLf _
& "Source: modTest.TestErrorLevel1" & vbCrLf & Err.Source
End Sub
Public Sub TestErrorLevel2()
On Error GoTo HandleErr ' clears Err object
TestErrorLevel3
Exit Sub
HandleErr:
' re-raise error, adding this subroutine to call chain
Err.Raise Err.Number, "modTest.TestErrorLevel2" & vbCrLf & Err.Source, Err.Description
End Sub
Public Sub TestErrorLevel3()
On Error GoTo HandleErr ' clears Err object
Err.Raise 1001 + vbObjectError, Description:="User-defined error. Offset range from 0 to 65535"
Exit Sub
HandleErr:
' re-raise: add module and routine to originating error
Err.Raise Err.Number, "modTest.TestErrorLevel3" & vbCrLf & Err.Source, Err.Description
End Sub
我的问题是:如何在 class 中正确引发错误,以便实例化 class 的调用者可以使用正确的错误处理技术?
我正在升级未使用 classes 的旧 VB6 意大利面条代码。过去我总是使用 On Error Resume Next 和 On Error Goto myLabel 用于在备选方案对我的代码没有任何清洁效果时处理错误。
但是,我无法让调用者处理错误,因为如果我在方法或 class 的 属性 中引发错误,无论我是否使用 On Error 语句从调用者那里捕获它。示例代码如下所示:
我的班级:
Public Sub Bar()
If valid Then
'some code here
Else
Err.Raise 5
End if
End Sub
主窗体:
Private Sub CallFoo()
Dim foo as New MyClass
On Error Goto fooliure 'Starts ignoring errors
Call foo.Bar() 'Program stops with an exception
On Error Goto 0 'Ends error handling
Exit Sub
fooliure:
'Error handling code
End Sub
Microsoft 还表示,这就是他们打算在 VB 6.0 中执行错误处理的方式,如前所述 here。
此时我正在考虑在我的 class 中使用一个对象来收集调用者可以检索的错误。如果我能避免那样做,我会的,但到目前为止我还没有找到答案。
David,这是关于 VBA 错误处理 101 的简短教程。
Err
对象。这是一个保存当前错误的单例对象。不要尝试实例化此对象(即不要使用Set objErr = New Err
——这会失败)On Error
- 设置错误处理。可能的错误处理程序:On Error GoTo Label
- 遇到错误时执行跳转到Label
On Error Resume Next
- 执行遇到错误时跳转到下一行On Error GoTo 0
- 关闭当前错误处理程序。任何后续错误将由调用者处理On Error Resume
- 执行跳转到导致错误的行(不推荐)
Err
对象在以下情况下被清除(丢失当前错误):- 子程序、函数或属性被调用
- 子程序、函数或属性正常退出
- 一个
On Error
语句被执行 Err.Clear
调用时清除当前错误
引发异常。您可以在需要时随时提出错误。规范形式:
Err.Raise 1001 + vbObjectError, Description:="An exception occurred."
- 自定义错误:使用
vbObjectError
来生成用户定义的错误。例子:1001 + vbObjectError
- 整数范围是0到65535
- 错误处理顺序:
- 如果例程中定义了本地错误处理程序,则执行它
- 如果没有本地处理程序,则向调用者抛出错误
- 如果调用者没有处理程序,则不断引发错误,直到找到本地处理程序
- 如果没有顶级处理程序,应用程序终止
- 创建错误链。创建显示原始错误的错误链并在错误发生时显示堆栈上的例程列表非常有用。去做这个:
- 向每个 可能导致错误的例程添加错误处理
- 始终向调用者重新提出错误
- 在重新引发错误时将字符串添加到
Err.Source
命名例程 - 顶层调用例程可以使用
MsgBox
来通知用户错误(或者可以实现其他日志记录)
下面是演示这些想法的代码示例:
Public Sub TestErrorLevel1()
On Error GoTo HandleErr ' clears Err object
TestErrorLevel2
Exit Sub
HandleErr:
' top-level error handler -- nothing else to raise error to
' show error and complete call chain
MsgBox "Error: " & Err.Number & vbCrLf & Err.Description & vbCrLf _
& "Source: modTest.TestErrorLevel1" & vbCrLf & Err.Source
End Sub
Public Sub TestErrorLevel2()
On Error GoTo HandleErr ' clears Err object
TestErrorLevel3
Exit Sub
HandleErr:
' re-raise error, adding this subroutine to call chain
Err.Raise Err.Number, "modTest.TestErrorLevel2" & vbCrLf & Err.Source, Err.Description
End Sub
Public Sub TestErrorLevel3()
On Error GoTo HandleErr ' clears Err object
Err.Raise 1001 + vbObjectError, Description:="User-defined error. Offset range from 0 to 65535"
Exit Sub
HandleErr:
' re-raise: add module and routine to originating error
Err.Raise Err.Number, "modTest.TestErrorLevel3" & vbCrLf & Err.Source, Err.Description
End Sub