为啥 ByRef 不能与 WithEvents 一起使用?

Posted

技术标签:

【中文标题】为啥 ByRef 不能与 WithEvents 一起使用?【英文标题】:Why does ByRef not work in conjunction with WithEvents?为什么 ByRef 不能与 WithEvents 一起使用? 【发布时间】:2013-07-02 08:37:33 【问题描述】:

我想我很清楚VB中ByValByRef之间的区别是什么,但我的问题是当我尝试将它与WithEvents声明的成员一起使用时。

我有以下方法:

Private Sub SafeCloseAndDeRefConnection(ByRef cnx As ADODB.Connection)
On Error GoTo ErrH
    If Not cnx Is Nothing Then
        If (cnx.State And adStateConnecting) = adStateConnecting Then
            cnx.Cancel
        End If

        If (cnx.State And adStateOpen) = adStateOpen Then
            cnx.Close
        End If

        Set cnx = Nothing
    End If
Exit Sub
ErrH:
 Set cnx = Nothing
End Sub

如果我有一个这样声明的类成员:

Private WithEvents Connection As ADODB.Connection

然后我想关闭连接,然后这样调用它:

SafeCloseAndDeRefConnection Connection

但在调用SafeCloseAndDeRefConnection 之后,Connection 变量没有设置为Nothing,并且仍然具有其原始引用。

如果我删除 WithEvents 关键字,则对 SafeCloseAndDeRefConnection 的调用将按预期工作(但显然无法处理事件)

谁能向我解释为什么会这样?

附:我找到了一个类似的question elsewhere,但解决方法在我的场景中不起作用。

【问题讨论】:

无法传递WithEvents 对象ByRef,如果您尝试它,则传递“副本”,就像您声明它ByVal 一样。它必须以这种方式来管理连接和断开实际对象的传出事件接口和客户端的接收器对象。 尝试实现一个“流利的”功能,然后你可以像这样使用它Set Connection = SafeCloseAndDeRefConnection(Connection) @Bob77 感谢您的回复。这有点道理(尽可能多的 VB 可以说得通)。您是否有更详细解释的参考? VB6 是一种“Web 2.0 之前的”语言,因此这方面的帮助有些分散,在网络上也不容易找到。 该机制的细节是Windows主题,而不是VB6主题。 VB6 努力消除了解此类实现细节的需要。您可以在msdn.microsoft.com/en-us/library/windows/desktop/… 尝试“COM 和可连接对象中的事件” 【参考方案1】:

或许调用:

Set Connection = Nothing

SafeCloseAndDeRefConnection(Connection)之后

这将强制销毁对象,而不是依赖VB6为你做!

【讨论】:

有点违背了该方法最初存在的目的。

以上是关于为啥 ByRef 不能与 WithEvents 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

optional [byval byref] [paramarray] 变量名() as 数据类型

VBA ByRef Argument Type Mismatch string into string

在运行时测试传入的 ByRef 参数是不是与给定的“其他”变量共享存储位置

ByRef 参数类型与布尔值不匹配

JavaScript 传播语法与 jQuery $.extend - ByRef 和 ByVal

VBA中ByVal和 ByRef有啥区别?