Collections Are Cool!

Collections Are Cool!

ntil recently, Visual FoxPro developers wanting to use collections often created their own classes that were nothing more than fancy wrappers for arrays. However, in addition to being a lot of code to write, home-built collections don’t support the FOR EACH syntax, which is especially awkward when they’re exposed in COM servers. Visual FoxPro 8.0 solves this problem by providing a true Collection base class. Collections are a common way to store multiple instances of things. For example, a TreeView control has a Nodes collection and Microsoft Word has a Documents collection.

The Collection base class has only a few properties, events, and methods. The Add method adds an item to the collection, the Remove method removes an item, and the Item method returns an item. The Count property indicates how many items are in the collection. An “item” can be a scalar value such as text or a number, but most commonly is an object. In addition to the item itself, the collection can store a key for the item, such as a name. An item can be located in the collection by:

  • Position: Collection.Item(2) returns the second item in the collection
  • Key: Collection.Item(‘Doug’) returns the item that has “Doug” as its key

Since Item is the default method, you can omit it if desired; Collection.Item(2) and Collection(2) do the same thing.

Collections can be simple replacements for arrays. Each item in a collection is similar to a row in an array. However, because they’re objects, collections have many more capabilities than arrays. This article will look at three specific uses for collections.

Use Collections Instead of Arrays
Some objects need to store a collection of things. For example, a forms manager needs information about every open form in an application. In addition to an object reference to the form, it may also keep information about which toolbar the form uses (so you don’t have multiple instances of the same toolbar), whether the form was added to the Window menu or not, the instance number of the form (in case the same form can be opened more than once), and so on. Until VFP 8, this information was often kept in an array, with one row per form and one column for each type of information.

However, as the number of columns increases, it becomes more and more difficult to keep track of what’s in the array and where. Was it the fourth column that stored the instance number or the seventh? Also, because arrays in VFP can’t have 0 rows, you have to be careful removing items from the array when a form is closed:

   lnForms = alen(This.aForms, 1) ? 1   lnCols  = alen(This.aForms, 2)   if lnForms = 0     This.aForms = .NULL.   else   * lnForm is the row number of the closed form     adel(This.aForms, lnForm)     dimension This.aForms[lnForms, lnCols]   endif

This complexity disappears when you use a collection. Instead of a row in an array, a form is represented by an object in a collection. The object contains a reference to the form and the other information required. Which code would you rather write (or read, for that matter) to find the instance number of a form?

   * Array-based code   lnPos = ascan(This.aForms, 'CustomerForm')   lnRow = asubscript(This.aForms, lnPos, 1)   lnInstance = This.aForms[lnRow, 4]   * Collection-based code   lnInstance = ;     This.oForms('CustomerForm').nInstance

Removing an object from the collection is easy, because there’s no need to worry about array dimensions. Simply call the Remove method of the collection.

Pass Collections as Parameters
Suppose you want to call a function that fills an array and the array is a member of an object. Other than a kidney stone, there isn’t anything harder to pass than a member array. Since arrays must be passed by reference using the @ operator, and you can’t use @ with a member array, you have to pass a local array and then ACOPY() the local array into the member array. However, to avoid an error, you must DIMENSION the member array properly first. I have a lot of code similar to this in various applications:

   dimension laItems[1]   SomeFunction(@laItems)   lnRows = alen(laItems, 1)   lnCols = alen(laItems, 2)   dimension This.aItems(lnRows, lnCols)   acopy(laItems, This.aItems)

Using a member collection rather than a member array (and assuming SomeFunction can work with a collection), this becomes as simple as:

   This.oItems = createobject('Collection')   SomeFunction(This.oItems)

Use Collections of Collections
The items in a collection can be anything, including other collections. In addition to acting like multi-dimensional arrays, collections of collections allow you to address objects at any level of detail using simple syntax.

Suppose you want to work with metadata. Wouldn’t it be nice to retrieve the data type for a field using code like the following?


If Tables is a collection of Table objects, and a Table object has a Fields collection of Field objects, and a Field object has a DataType property, this is easily done.

Listing 1 shows an example of this. The Init method of the Tables class populates the collections of tables and fields by reading metadata from a table called CoreMeta.dbf. This table has columns of information about tables and fields, including cRecType (“T”) for a table and “F” for a field), cObjectNam (the name of the table or field), and cType (the data type of a field).

To determine the number of fields in the Customer table, use the following:


You can get the descriptive name for the Orders.Order_Date field with this:


The new VFP 8 Collection base class makes it easy to create and work with collections of items. While arrays still have their place, I predict collections will replace them in the majority of uses in applications as VFP developers become more familiar with them.

Share the Post:
XDR solutions

The Benefits of Using XDR Solutions

Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved

AI is revolutionizing fraud detection

How AI is Revolutionizing Fraud Detection

Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across

AI innovation

Companies Leading AI Innovation in 2023

Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several

data fivetran pricing

Fivetran Pricing Explained

One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of

kubernetes logging

Kubernetes Logging: What You Need to Know

Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes

ransomware cyber attack

Why Is Ransomware Such a Major Threat?

One of the most significant cyber threats faced by modern organizations is a ransomware attack. Ransomware attacks have grown in both sophistication and frequency over the past few years, forcing

data dictionary

Tools You Need to Make a Data Dictionary

Data dictionaries are crucial for organizations of all sizes that deal with large amounts of data. they are centralized repositories of all the data in organizations, including metadata such as