Practical Standards for Microsoft Visual Basic .NET (Pro-Developer)
[Previous] [Next]
Enumerations are similar to constants in that they are named entities that are assigned values. However, enumerations behave like groups of public constants in a module. They're treated as data types, and you use them to create constants of suitable values for variables and properties. You might already be using enumerations in Visual Basic. For instance, when you use the MsgBox statement, Visual Basic's Auto List Members feature displays a drop-down list (commonly referred to as the "code helper drop-down list") for the Buttons parameter. (See Figure 5-1.)
Figure 5-1. Enumerations eliminate the need to memorize many different parameter values.
The time that the developers of the MsgBox statement invested to provide the Buttons parameter's values in an enumeration pays you dividends as a programmer. You never have to remember the numeric values of the parameter, and the chance of incorrectly specifying a value is greatly diminished. Although you can still specify a numeric value for a parameter rather than the name of an enumeration member, you should never do so . To actually use a magic number when an associated member name is available is just south of insane.
Creating Custom Enumerations
You create enumerations much like you do user -defined data types. In the Declarations section of a module, you type the word Public or Private , type Enum , and then type the name of your custom enumeration. The following is a sample enumeration:
Public Enum otBorderStyle otNone = 0 otRaised_Light = 1 otRaised_Heavy = 2 otSunken_Light = 3 otSunken_Heavy = 4 End Enum |
This enumeration creates an enumerated type with five values. Although you always refer to the name of an enumeration member when you write code, the name simply represents its numeric value, much like a constant. All members of enumerations are long integers; you can't use other data types.
Using a Custom Enumeration
Once you've created an enumeration, you can use it as the data type for any variable, Function procedure, or Property procedure within the scope of the enumeration. For instance, to create a BorderStyle property that uses the enumerated type shown previously, you can declare a procedure like this:
Public Property Let BorderStyle(lngNew_BorderStyle _ As otBorderStyle) |
This property procedure accepts a value into the parameter lngNew_BorderStyle. lngNew_BorderStyle is a long integer because it is declared as an enumerated type and all members of enumerations are long integers. When you reference this property in code, Visual Basic displays the code helper drop-down list with all the enumeration members, as shown in Figure 5-2.
Figure 5-2. Custom enumerations offer the same advantages and behavior as system enumerations.
You can also use an enumerated type as the data type returned by a function or a Property procedure. For instance, to create the Property Get procedure that corresponds to the previous Property Let procedure, you can use code like this:
Public Property Get BorderStyle() As otBorderStyle |
Note that simply declaring a parameter as an enumerated type does not guarantee that the value passed to the parameter will be one of the defined enumeration members. As a matter of fact, this is one of the most common misconceptions about enumerated types. When you define an enumeration, you define a list of named values, but these are not the only values that a parameter of that enumerated type will accept. As mentioned previously, parameters that are defined as enumerated types are actually long integers. As such, they accept any value that fits into a long integer; Visual Basic does not confirm that the number passed into a parameter corresponds to a member of the enumeration. For this reason, you should always validate the data passed to a parameter declared as an enumerated type, as I'll discuss in Directive 5.8.
Goals of Using Constants and Enumerations
The goals of using constants and enumerations include
- Reducing errors caused by transposing or mistyping numbers
- Making it easy to change values in the future
- Making code easier to read
- Ensuring forward compatibility