The data types you've learned about so far hold strings, integers, dates, and other predefined kinds of information, but sometimes it would be nice to define your own data types. You might like to be able to make a data type that can hold only certain values, such as a MealType
data type that can hold the values Breakfast, Lunch
, and Dinner
. You might also like to define a type to hold related pieces of data (such as name, address, and phone number) in a single variable.
Enumerations and structures enable you to do these things. An enumeration (or enumerated type) enables you to define a new data type that can take only one of an allowed list of values. A structure enables you to define a group of related pieces of data that should be kept together.
In this lesson, you learn how to define and use enumerations and structures to make your code easier to understand and debug.
An enumeration is simply a data type that allows only specific values. The following code defines a ContactMethod
enumeration that can hold the values None, Email, Phone
, or SnailMail
:
' Define possible contact methods. Private Enum ContactMethod As Integer None = 0 Email Phone SnailMail End Enum
Internally, an enumeration is stored as an integral data type, by default an Integer
. A number after a value tells Visual Basic explicitly which integer to assign to that value. In the preceding code, None
is explicitly assigned the value 0
.
If you don't specify a value for an enumeration's item (and often you don't care what these values are), its value is one greater than the previous item's value (the first item gets the value 0). In this example, None
is 0, Email
is 1, Phone
is 2
, and SnailMail
is 3
.
You create an instance of an enumerated type just as you make an instance of a primitive type such as Integer, Decimal
, or String
. The following code declares a variable of type ContactMethod
, assigns it the value ContactMethod.Email
, and then displays its value in a message box:
Dim method As ContactMethod = ContactMethod.Email MessageBox.Show(method.ToString())
An enumeration's ToString
method returns the value's name, in this case "Email."
Defining a structure is easy. The following code defines a simple structure named Address
that holds name and address information:
' Define a structure to hold addresses. Private Structure Address Public Name As String Public Street As String Public City As String Public State As String Public Zip As String Public Email As String Public Phone As String Public PreferredMethod As ContactMethod End Structure
The structure begins with a Structure
statement that defines the structure's name and ends with an End Structure
statement. The lines in between define the pieces of data that the structure holds together. The Public
keywords in this example mean that the fields inside the structure (Name, Street
, and so on) are visible to any code that can see an Address
.
Notice that the structure can use an enumeration. In this example, the Address
structure's PreferredMethod
field has type ContactMethod
.
In many ways structures behave like simple built-in types such as Integer
and Single
. In particular, when you declare a variable with a structure type, the code not only declares it but also creates it. That means you don't need to use the New
keyword to create a structure.
After defining a structure variable, you can access its fields using syntax similar to the way you access a control's properties. Start with the variable's name, follow it with a dot, and then add the field's name.
The following code creates and initializes a new Address
structure named homeAddress
:
Dim homeAddress As Address homeAddress.Name = txtName.Text homeAddress.Street = txtStreet.Text homeAddress.City = txtCity.Text homeAddress.State = txtState.Text homeAddress.Zip = txtZip.Text homeAddress.Email = txtEmail.Text homeAddress.Phone = txtPhone.Text homeAddress.PreferredMethod = CType(cboMethod.SelectedIndex, ContactMethod)
This code fills in the text fields using values entered by the user in textboxes.
The final field is a ContactMethod
enumeration. The user selects a value for this field from the cboMethod ComboBox
. The code takes the index of the ComboBox
's selected item, uses CType
to convert it from an integer into a ContactMethod
, and saves the result in the structure's PreferredMethod
field.
To correctly convert a ComboBox
selection into an enumeration value, the ComboBox
must display the choices in the same order in which they are defined by the enumeration. In this example, the ComboBox
must contain the items None, Email, Phone, and SnailMail, in that order, to match up with the enumeration's items.
In many ways structures are very similar to classes. Lessons 23 through 30 say a lot more about classes and the sorts of things you can do with them, and many of the same techniques apply to structures.
For example, both can contain properties, methods, and events. Both can also have constructors, special methods that are executed when you use New
to create a new one.
While structures and classes have many things in common, they also have many differences. A lot of these differences are outside the scope of this book, so I won't cover them here, but one very important difference that you should understand is that structures are value types, whereas classes are reference types.
A reference type variable doesn't actually hold an instance of a class. Instead it holds a reference to an instance. For example, the following code creates a reference to an object of type NewUserForm
. The second statement actually creates that instance and then the third statement displays it. If you tried to display the form without the second statement, the program would crash because the variable wouldn't be referring to an instance yet.
Dim userForm As NewUserForm userForm = New NewUserForm() userForm.ShowDialog()
In contrast, a value type variable actually contains its data instead of referring to it. For example, the following code declares an Address
variable. After the first statement, the variable already contains an Address
structure, its fields have default values, and it is ready for use.
Dim homeAddress As Address homeAddress.Name = "Benjamin"
One other important difference between value and reference types is that when you set a variable with a value type equal to another, the first variable receives a copy of the second variable's value. For example, if x
and y
are integers, then the statement x = y
makes x
hold the same value as y
.
Similarly, if ann
and ben
are variables of the structure type Person
, then ben = ann
makes all of the fields in ben
have the same values as all of the fields in ann
, but they are still two separate Person
structures.
In contrast, if you set a reference type variable equal to another, the first variable now refers to the same object as the other, not just a copy of that object. For example, suppose cindy
and dan
are two variables that hold references to Student
objects. The statement dan = cindy
makes the variable dan
refer to the same object to which cindy
refers. If you change one of dan
's properties, cindy
also sees the change because they point to the same object.
The StructureVersusClass example program that is available in the Lesson 17 download demonstrates this difference.
So which should you use, a structure or a class? In many programs the difference doesn't matter much. As long as you are aware of the relevant differences, you can often use either.
Microsoft's "Classes and Structs (C# Programming Guide)" web page at msdn.microsoft.com/library/ms173109.aspx
gives the following advice (though that page is discussing C# programming, its advice also applies to Visual Basic):
In general, classes are used to model more complex behavior, or data that is intended to be modified after a class object is created. Structs are best suited for small data structures that contain primarily data that is not intended to be modified after the struct is created.
In this Try It, you use an enumeration and a structure to make the address book shown in Figure 17-1. When the user clicks the Add button, the program saves the entered address values. If the user enters a name and clicks Find, the program retrieves the corresponding address data.
You can download the code and resources for this Try It from the book's web page at www.wrox.com
or www.vb-helper.com/24hourvb.html
. You can find them in the Lesson17 folder in the download.
In this lesson:
Create the form shown in Figure 17-1.
Define the ContactMethod
enumeration with values None, Email, Phone
, and SnailMail
.
Define an Address
structure to hold the entered address information.
Create a Dictionary(Of String, Address)
field to hold the address data.
Add code to initially select the ComboBox
's None
entry when the form loads (just so something is selected).
Add code to the Add button that creates the new entry in the Dictionary
.
Add code to the Find button that retrieves the appropriate entry from the Dictionary
and displays it.
Remember to add the choices to the ComboBox
in the same order they are defined in the ContactMethod
enumeration.
Use CType
to convert from a ComboBox
's selected index to a ContactMethod
.
Use CInt
to convert from a ContactMethod
to a ComboBox
's selected index.
Create the form shown in Figure 17-1.
This is relatively straightforward.
Define the ContactMethod
enumeration with values None, Email, Phone
, and SnailMail
.
Use code similar to the following:
' Define possible contact methods. Private Enum ContactMethod None = 0 Email Phone SnailMail End Enum
Define an Address
structure to hold the entered address information.
Use code similar to the following:
' Define a structure to hold addresses. Private Structure Address Public Name As String Public Street As String Public City As String Public State As String Public Zip As String Public Email As String Public Phone As String Public PreferredMethod As ContactMethod End Structure
Create a Dictionary(Of String, Address)
field to hold the address data.
Use code similar to the following:
' Make a Dictionary to hold addresses. Private Addresses As New Dictionary(Of String, Address)()
Add code to initially select the ComboBox
's None
entry when the form loads.
Use code similar to the following:
cboMethod.SelectedIndex = 0
Add code to the Add button that creates the new entry in the Dictionary
.
Use code similar to the following. Optionally, you can clear the TextBoxes
to get ready for the next address.
' Add a new address. Private Sub btnAdd_Click() Handles btnAdd.Click Dim newAddress As Address newAddress.Name = txtName.Text newAddress.Street = txtStreet.Text newAddress.City = txtCity.Text newAddress.State = txtState.Text newAddress.Zip = txtZip.Text newAddress.Email = txtEmail.Text newAddress.Phone = txtPhone.Text newAddress.PreferredMethod = CType(cboMethod.SelectedIndex, ContactMethod) ' Add the name and address to the dictionary. Addresses.Add(txtname.Text, newAddress) ' Get ready for the next one. txtName.Clear() txtStreet.Clear() txtCity.Clear() txtState.Clear() txtZip.Clear()
txtEmail.Clear() txtPhone.Clear() cboMethod.SelectedIndex = 0 txtname.Focus() End Sub
Add code to the Find button that retrieves the appropriate entry from the Dictionary
and displays it.
Use code similar to the following:
' Look up an address. Private Sub btnFind_Click() Handles btnFind.Click ' Get the Address. Dim selectedAddress As Address = Addresses(txtName.Text) ' Display the Address's values. txtname.Text = selectedAddress.Name txtStreet.Text = selectedAddress.Street txtCity.Text = selectedAddress.City txtState.Text = selectedAddress.State txtZip.Text = selectedAddress.Zip txtEmail.Text = selectedAddress.Email txtPhone.Text = selectedAddress.Phone cboMethod.SelectedIndex = CInt(selectedAddress.PreferredMethod) End Sub
Please select Lesson 17 on the DVD to view the video that accompanies this lesson.
Copy the program you built for this lesson's Try It. Add a Remove button that removes an item by calling the Dictionary
's Remove
method.
Copy the program you built for Exercise 1. Modify it by adding a new integer Id
field to the structure. Then create a second Dictionary
that uses Id
as its key. Allow the user to click the Find by Name or Find by ID buttons to locate an item using either the customer's name or ID. Also provide Remove buttons that remove by name or ID. (Hint: When the user clicks a Remove button, be sure to remove the item from both Dictionaries
.)
Make a program to store appointment data similar to the program you built for Exercise 1. Use a structure with the following fields: Time, Attendees, Type, Topic
, and Notes
. Make Type
come from the AppointmentType
enumeration that includes the values None, Work, Home
, and Other
. (Hint: See Lesson 16's Exercise 4 for tips on how to use a DateTimePicker
control's values as keys.)
You can find solutions to this lesson's exercises in the Lesson17 folder inside the download available on the book's web site at www.wrox.com
or www.vb-helper.com/24hourvb.html
.