Circular Referencing to COM Objects

Why Avoid the Reference Count?

Well, under normal circumstances, you should not avoid it. But, there are some cases where this is actually useful. The most obvious of all is a Parent property in a COM object. A Parent property is a circular reference that causes the parent object to stay in memory even when required to unload, that is, if you are not careful.

Let us pose an example: Any VB control (yes, I know, not very specific; make that a textbox then). They all have a Parent property that returns a reference to the form where they reside.

You can test the parent property by using the following code. Just create a new VB project, add a textbox called Text1, and add the presented code into the click event of a Command button.

Dim myForm as Form

set myForm = Text1.Parent
Debug.Print myForm.Caption

Well, lets now complicate things a bit. Imagine you would like to create a control similar to a ListView control. As you probably know, ListViews provide access to its elements in the form of ListItem objects. This item objects can return its parent, just like the textbox in the example above.

NOTE: I will not be presenting full coding (take the collection declaration as an example) because it is not the purpose of this article to show you how to, for example, create a collection class. If you want to learn how to create one, I suggest you play with the Class Builder Add-in for Visual Basic. The same goes for similar subjects.

So you start creating your control named SuperListBox, and in the process, you add a class module and call it SuperListItem. Then, you add a property called "Parent", and you code it like this:

Option Explicit

'Private instance of the parent
Private mvarParent as SuperListBox

'Now you add the property code
Public Property Get Parent() as SuperListBox
    Set Parent = mvarParent
End Property

'You make the Set part of the property a Friend procedure,
'just to make sure the end programmer will not mess with it
Friend Property Set Parent(ByVal oNewParent as SuperListBox)
    mvarParent = oNewParent
End Property

Nice. The parent property is done. Also, you decide to create a collection class, called SuperListItems to hold all the items being created. Sounds good to me. Furthermore, whenever you create a new SuperListItem object, you'll be setting its Parent property before any other code and before returning the object to the host program, and you will also be adding the new list item to the collection. Simple:

Dim oNewItem as SuperListItem

Set oNewItem = New SuperListItem
Set oNewItem.Parent = Me
oMyCollection.Add oNewItem

Finally, you, as good fellow who likes to do things by the book, add to the Terminate event the following lines, to be sure you are cleaning up your mess:

Private Sub Usercontrol_Terminate()
    Set oMyCollection = Nothing
End Sub

Just to demonstrate my point here, add the line Debug.Print "Terminating" in the Usercontrol_Terminate event.

Good. Now everything is set. You test your control by creating, in a standard project, a few list items and such. Then finish the program and check the debug window. You will NOT find the "Terminating" message that we were expecting!! Why??? I already explained that. The COM object instance of your control is still referenced! Its reference count is not zero. There is one reference per ListItem to the instance of your usercontrol. But why this happens if you added the cleanup code and all!!?? Well, the cleanup code never runs because the object never starts its own destruction in the first place.

"But I really need the Parent Property in place!!", you say. I know that. Turn the page to learn the solution: Soft referencing"

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“An expert is a man who has made all the mistakes that can be made in a very narrow field” - Niels Bohr