3
以下代碼爲集合中的每個元素創建一個循環引用。 UserForm_Terminate
例程中的代碼是否足以拆除關係以允許釋放內存?還是需要使用指針和弱引用?拆除循環引用
如果是這樣/不是測試對象是否被釋放的最佳方法是什麼?
用戶窗體代碼:
Option Explicit
Implements IBtnClick
Dim coll As Collection
Private Sub UserForm_Initialize()
Dim x As Long
Dim e As CBtnEvents
Set coll = New Collection
For x = 1 To 5
Set e = New CBtnEvents
Set e.btn = Me.Controls.Add("Forms.CommandButton.1")
e.ID = x
e.Register Me
With e.btn
.Height = 30
.Width = 30
.Top = 10
.Left = .Width * x
End With
coll.Add e
Next x
End Sub
Private Sub UserForm_Terminate()
Dim itm
For Each itm In coll
msgbox itm.ID
itm.Unregister
Next itm
End Sub
Private Sub IBtnClick_click(ID As Long)
MsgBox ID
End Sub
IBtnClick代碼:
Public Sub click(ID As Long)
End Sub
CBtnEvents代碼:
Private WithEvents p_btn As MSForms.CommandButton
Private p_ID As Long
Private click As IBtnClick
Public Property Set btn(value As MSForms.CommandButton)
Set p_btn = value
End Property
Public Property Get btn() As MSForms.CommandButton
Set btn = p_btn
End Property
Public Sub Register(value As IBtnClick)
Set click = value
End Sub
Public Sub Unregister()
Set click = Nothing
End Sub
Private Sub p_btn_Click()
click.click p_ID
End Sub
Public Property Get ID() As Long
ID = p_ID
End Property
Public Property Let ID(ByVal lID As Long)
p_ID = lID
End Property
Private Sub Class_Terminate()
MsgBox p_ID
End Sub
我已經包含了VB6的標籤,因爲我覺得這個問題也同樣適用,但我我正在使用Excel VBA。
您不能使用UserForm_Terminate來拆除子對象,因爲如果子對象持有引用它永遠不會被觸發。使用'Unload','QueryUnload'或其他用戶生成的事件。最好是有一個單獨的Terminate方法,所以你可以手動或從用戶事件impl調用它。 – wqw
'UserForm_Terminate'雖然被觸發了,但是我可以遍歷代碼,每個CBtnEvents的'Class_Terminate'也被觸發。我已經在子類終止例程中添加了一個msgbox以上面的代碼來演示 – SWa
我看到了。 'CBtnEvents'沒有引用回'UserForm',而是一個'CommandButton'放在它上面。那麼你不必明確地拆卸,(隱式地)銷燬'coll'就可以完成清理工作。在各種Terminate事件中放置Debug.Print。我手動支持一個簿記集合,將作爲答案發布。 – wqw