Structures are very similar to classes. The syntax for declaring a structure is as follows:
[attribute_list] [Partial] [accessibility] [Shadows] _ Structure name[(Of type_list)] [Implements interface] statements End Structure
The only thing that all structure declarations must include is the Structure clause and the End Structure statement. The rest is optional.
Unlike a class, however, a structure cannot be empty. It must contain at least one variable or event declaration. The following code describes a valid structure. Its only member is a Private variable, so this structure wouldn’t be of much use, but it is valid.
Structure EmptyStructure Private m_Num As Integer End Structure
The structure’s attribute_list and accessibility clauses, Shadows and Partial keywords, and the Implements statement are the same as those for classes. See the sections “attribute_list” and “accessibility” earlier in this chapter for details.
There are two main differences between a structure and a class: Structures cannot inherit and structures are value types rather than reference types.
A structure cannot inherit, so it cannot use the MustInherit, NotInheritable, or Inherits keywords. However, a structure can implement any number of interfaces. The following code declares the IPerson interface, which defines the FirstName and LastName properties. The Employee structure implements this interface, providing code to handle those properties and adding two new variables named OfficeNumber and Extension.
Public Interface IPerson Property FirstName() As String Property LastName() As String End Interface Public Structure Employee Implements IPerson Public OfficeNumber As String Public Extension As String Private m_FirstName As String Private m_LastName As String Public Property FirstName() As String Implements IPerson.FirstName Get Return m_FirstName End Get Set(ByVal value As String) m_FirstName = value End Set End Property Public Property LastName() As String Implements IPerson.LastName Get Return m_LastName End Get Set(ByVal value As String) m_LastName = value End Set End Property End Structure
The biggest difference between a structure and a class is in how each allocates memory for its data. Classes are reference types. That means an instance of a class is actually a reference to the object’s storage in memory. When you create an instance of a class, Visual Basic actually creates a 4-byte value that points to the object’s actual location in memory.
On the other hand, structures are value types. An instance of a structure contains the data inside the structure rather than simply pointing to it. Figure 16-1 illustrates the difference.
Figure 16-1: A structure contains the data, while a class object contains a reference that points to data.
The difference between reference and value type has several important consequences that are described in the following sections.
The difference in memory required by classes and structures is small when you consider only a single object. If you look at an array, however, the distinction is more important. An array of class objects contains references to data in some other part of memory. When you first declare the array, the references all have the value Nothing, so they don’t point to any data and no memory is allocated for the data. The references take 4 bytes each, so the array uses only 4 bytes per array entry.
An array of structure instances, on the other hand, allocates space for the data inside the array. If each structure object takes up 1000 bytes of memory, then an array containing N items uses 1000 * N bytes of memory. Each structure object’s memory is allocated, whether its fields contain meaningful data or not.
Figure 16-2 illustrates this situation. The array of class objects on the left uses very little memory when the references are Nothing. The array of structure objects on the right uses a lot of memory even if its elements have not been initialized.
Figure 16-2: An array of class objects contains small references to data, many of which may be Nothing. An array of structures takes up a significant amount of memory.
If you must use a large array of objects where only a few at a time will have values other than Nothing, then using a class may save the program a considerable amount of memory. If you will need most of the objects to have values other than Nothing at the same time, it may be faster to allocate all the memory at once using a structure. This will also use slightly less memory, because an array of class references requires an extra 4 bytes per entry to hold the references.
Tip | In theory, you may see a slight performance benefit to using an array of structures if you want them initialized to default values. The array will be allocated and later freed in a single step, and its memory will be contiguous, so for some applications, this kind of array may reduce paging. The garbage collector can also mark the array’s memory as in use in a single step, while it must follow the references to class objects separately. In practice, however, the differences are so small that you should not use performance to decide which approach to use. Usually, you are best off picking the method that makes the most logical sense, and not worrying too much about the slight performance difference. |