gpt4 book ai didi

vba - 如果只能存在一个错误对象,那么声明 ErrObject 变量有什么用?

转载 作者:行者123 更新时间:2023-12-03 07:46:32 25 4
gpt4 key购买 nike

我们都知道 VBA 中只能有一个错误对象。
在帮助同事处理错误以及为什么他不应该使用 On Error Resume Next 时我有一个想法:
将错误对象存储在某处以供以后引用。

考虑这段测试代码:

Sub Test()
Dim t As ErrObject
On Error Resume Next
Err.Raise 1
Set t = Err
On Error GoTo 0
Debug.Print t.Number
On Error Resume Next
Err.Raise 1
Debug.Print t.Number
End Sub

因为 On Error GoTo 0,它将打印0到即时窗口。重置错误对象,然后打印 1,因为它仍然持有对唯一错误对象 (?) 的引用。

如果我们创建一个新类并给它一些与 ErrObject 相关的属性,如下所示:
(TestClass)
Option Explicit
Public oError As ErrObject
Private Sub Class_Initialize(): End Sub
Private Sub Class_Terminate()
If Not oError Is Nothing Then Set oError = Nothing
End Sub
Public Property Get Error()
Error = oError
End Property
Public Property Set Error(ByVal ErrorObject As ErrObject)
Set oError = ErrorObject
End Property

并像这样创建我们的实例:
Sub Test2()
Dim t As TestClass
On Error Resume Next
Set t = New TestClass
Err.Raise 1
Set t.Error = Err
On Error GoTo 0
Debug.Print t.oError.Number
On Error Resume Next
Err.Raise 1
Debug.Print t.oError.Number
End Sub

我们仍然分别得到 0 和 1 作为输出。

这让我想到了我的问题: 当我们无法创建新对象本身但它只是成为 VBA 中唯一错误对象的另一个指针时,将变量声明为 ErrObject 有什么用?

最佳答案

没有任何。
Err通常被视为某种全局 ErrObject例如,但事实是,它是一个返回一个的函数 - 正如对象浏览器中所揭示的:

enter image description here

并且该功能以这样一种方式实现,即您始终获得相同的对象。

对象需要公开一个接口(interface)才能使用,因此 Err 返回的对象函数公开 ErrObject 的函数类 - 这并不意味着 ErrObject类的存在是为了它可以被用户代码实例化或封装:它只是提供一个接口(interface)来访问当前运行时错误状态的属性。

当您封装 ErrObject就像你做的那样,你基本上只是给自己另一种方式(除了 Err 函数)来访问 ErrObject实例 - 但它仍然是保存当前运行时错误状态属性的完全相同的对象。

当一个对象的属性发生变化时,指向该对象的封装副本将开始报告新值,而您要“记住”的旧值将被覆盖。

请注意,这适用于任何对象,而不仅仅是 ErrObject .

假设我有一门课可以用 ErrObject 做你正在做的事情。引用,但带有 Collection :

Private coll As Collection

Public Property Set InternalCollection(ByVal c As Collection)
Set coll = c
End Property

Public Property Get InternalCollection() As Collection
Set InternalCollection = coll
End Property

如果我创建该类的一个实例(我们称之为 Class1 )并分配 c到它的 InternalCollection ,然后将项目添加到 c ...
Dim c As Collection
Set c = New Collection
With New Class1
Set .InternalCollection = c

c.Add 42
.InternalCollection.Add 42

Debug.Print .InternalCollection.Count
End With

输出为 2 , 因为 cInternalCollection (/封装的 coll 引用)是同一个对象,这就是封装的 ErrObject 所发生的事情.

解决方案是不封装 ErrObject本身,而是将其值拉入用于封装 ErrObject 状态的仅获取属性的支持字段中:
Private errNumber As Long
Private errDescription As String
'...

Public Sub SetErrorInfo() 'note: an ErrObject argument would be redundant!
With Err
errNumber = .Number
errDescription = .Description
'...
End With
End Sub

Public Property Get Number() As Long
Number = errNumber
End Property

Public Property Get Description() As String
Description = errDescription
End Property

'...

现在,这是否有用还有待商榷 - IMO 如果在全局错误状态已经包含相同信息的时刻消耗状态,则无需这样做。

该类很容易被 [ab] 用作 Function 的返回类型。返回 Nothing表示成功,以及在失败时封装的错误状态 - 问题在于该语言是围绕引发错误而不是返回错误而设计的;在不验证其返回值的情况下“一劳永逸”这样的函数太容易了,因为在调用站点实际运行时错误状态不会触发 On Error声明,将错误状态作为程序数据携带不是惯用的,它产生了一个“令人惊讶的”API,很容易导致代码最终忽略所有错误。

惯用的错误处理会尽快处理全局运行时错误状态,并且要么在同一范围内恢复,要么让错误状态在调用堆栈中冒泡到可以处理的地方。在处理错误之前, ErrObject状态可通过全局 Err 访问功能。

关于vba - 如果只能存在一个错误对象,那么声明 ErrObject 变量有什么用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55066376/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com