Reinstantiating an Object

Reinstantiating an Object

You normally instantiate a CDO library object by accessing a property on a parent object that causes the desired object to be created. For example, the statement

  Set objMsg = objSession.Inbox.Messages.Item(1)
 

instantiates a Folder object for the Inbox property of the Session object, then a Messages collection object for the Messages property of the Inbox folder, and then a Message object for the Item property of the Messages collection.

Every time you cross a period from left to right, you instantiate the object on the right of the period. This is true whether or not you have previously instantiated another version of the same object. This code fragment, for example, is intended to count the members of an AddressEntries collection that can resolve the name "John":

  Dim objAdrList As AddressList
  Dim objAEFilt As AddressEntryFilter
  Dim objAE As AddressEntry
  ...
  Set objAEFilt = objAdrList.AddressEntries.Filter
  objAEFilt.Name = "John" ' set filter to restrict on this name
  i = 0
  For Each objAE in objAdrList.AddressEntries
    i = i + 1
    MsgBox objAE.Name
  Next
 

As written, however, this code counts every AddressEntry object in the collection. This is because the collection itself is instantiated twice, once when setting the filter and once when initializing the loop, in response to the code objAdrList.AddressEntries. The second collection is instantiated with a default AddressEntryFilter object with no restrictions, which is used in the loop. The filter with the Name property restriction remains with the first collection and is never used.

This behavior is counterintuitive to programmers accustomed to having the same object returned by repeated references. But no variable is defined for an object that is generated internally by crossing a period, and Visual Basic has no way of correlating its internal objects. It is up to you to take care of the correlation at the source code level.

The proper approach is to define and Set a variable for any object you plan to use more than once. In the case of the previous code fragment, it is the AddressEntries collection object that is to be reused:

  Dim colAddrEntries As AddressEntries
  ...
  Set colAddrEntries = objAdrList.AddressEntries
  Set objAEFilt = colAddrEntries.Filter
  objAEFilt.Name = "John" ' set filter to restrict on this name
  i = 0
  For Each objAE in colAddrEntries
    i = i + 1
    MsgBox objAE.Name
  Next
 

C/C++ programmers should observe that the period in Visual Basic is not a class member access operator, nor is it a pointer. Although objAdrList.AddressEntries may appear analogous to a construction such as lpAdrList->AddressEntries, there is in fact very little parallelism between the two, and access to a property in C/C++ requires more than a single statement.

When you instantiate an object multiple times, you subject your application to several problems:

  • Your application wastes execution time and memory creating and retaining more than one version of the object.
  • A subsequent instantiation does not Release a previous one, and all instantiated objects remain in memory with nonzero reference counts.
  • The instantiations are unrelated to one another, and any operations you perform on one have no effect on any of the others.
  • A given instantiation is used only by the code that follows its creation and precedes a subsequent instantiation. That is, different sections of your code are using different, unrelated versions of the object.

The safest procedure is to use explicit variables for all the objects and collections in your application. The consequence of not doing so can vary from inefficient execution to wrong results. For more information, see Improving Application Performance.