An enumeration allows you to define your own set of named constants. A named constant is an item that preserve a constant value throughout the execution of a program and can be used in place of literal values. In other words, an Enum is nothing but a group of related constant values that automatically take different values. You can use named constants as property values, method arguments, and as a function's return values. By using a named constant it makes your code easier to read and maintain. For example, some properties are intended to return a well-defined subset of integer numbers. In our Student class, we can implement a YearLevel property that can be assigned the values 1 (Freshmen), 2 (Sophomore), 3 (Junior), and 4 (Senior).
' In the declaration section of the class Enum YearLevelEnum Freshmen = 1 Sophomore Junior Senior End Enum |
You don't need to assign an explicit value to all the items in the Enum structure, Visual Basic increments the preceding value automatically by 1. But because 0 is the default value for any Integer property when the class is created, Visual Basic starts at 0. It is a good programming style that you should always stay clear in assigning value to the enum list, so that you can later trap any value that hasn't been properly initialized . But Enum values don't need to be in an increasing sequence. In fact, you can provide special values for Enum constant list, as shown below:
' In the declaration section of the class Enum GradeEnum Falling = 50 Passing = 75 Probationary = 84 Except = 90 End Enum |
After you define an Enum structure, you can create a Public or Private property of the corresponding type:
Private m_YearLevel As YearLevelEnum Property Get YearLevel() As YearLevelEnum YearLevel= m_YearLevel End Property Property Let YearLevel(ByVal enumValue As YearLevelEnum) ' Refuse invalid assignments. If enumValue <= 0 Or enumValue > Senior Then Err.Raise 5 m_YearLevel= enumValue End Property |
You should never forget that Enums are just shortcuts for creating constants. This means that all the enumerated constants defined within an Enum block should have unique names in their scope. Typically Enums type are made by programmer to be Public, so their scope is often the entire application.
It is a good programming practice, that you should devise a method for generating unique names for all your enumerated constants. If you fail to do that, the compiler refuses to compile your application and raises the "Ambiguous name detected: <itemname>" error. The easy way to avoid this problem is to add to all the enumerated constants a unique 2 or 3 letter prefix, for example:
' In the declaration section of the class Enum YearLevelEnum lvlFreshmen = 1 lvlSophomore lvlJunior lvlSenior End Enum |
Another way to avoid ambiguous name problem is use the complete enumname.constantname syntax whenever you refer to an ambiguous Enum member, as in the following code:
Student.YearLevel = YearLevelEnum.lvlSenior |
While enumerated properties are very useful and allow you to store some descriptive information in just 4 bytes of memory, sooner or later you will have to extract and decode this information and sometimes even show it to your users. For this reason, It is a good programming practice to add a read-only property that returns the description of an enumerated property:
Property Get YearLevelDescription() As String Select Case m_YearLevel Case lvlFreshmen : YearLevelDescription = "Freshmen" Case lvlSophomore: YearLevelDescription = "Sophomore" Case lvlJunior: YearLevelDescription = "Junior" Case lvlSenior: YearLevelDescription = "Senior" Case Else: Err.Raise 5 End Select End Property |
Another issue that you should never forget that your class are often change its structure if you are still in developing stage. So it is possible that your validation code can become outdated. For example, what happens if you later add a fifth YearLevel constant such Graduate or Masteral? For this reason, you should always add new constants safely without modifying the validation code in the corresponding Property Let procedure, one way to do this is create a enum constant as the highest value in that block and assign the value that you wanted to be the last enum constant, as shown below:
' In the declaration section of the class Enum YearLevelEnum lvlFreshmen = 1 lvlSophomore lvlJunior lvlSenior lvlGraduate ' newly added enum constant lvlMasteral ' newly added enum constant YEAR_LEVEL_MAX = lvlMasteral ' make lvlMasteral the last enum constant End Enum Property Let YearLevel(ByVal enumValue As YearLevelEnum) ' Refuse invalid assignments If enumValue <= 0 Or enumValue > YEAR_LEVEL_MAX Then Err.Raise 5 m_YearLevel= enumValue End Property |
As you can see we can safely add a new enum constant without worrying about the validation code in our Property Let to become obsolete. And making our maximum value in uppercase and putting a comment, we can easily spot it in our source code. Of course, you should account your read-only property description, because adding new enum constant in our enumblock without adding appropriate description our YearLevelDescription property will result to an error, but at least we are safely notified.
' Modified version Property Get YearLevelDescription() As String Select Case m_YearLevel Case lvlFreshmen: YearLevelDescription = "Freshmen" Case lvlSophomore: YearLevelDescription = "Sophomore" Case lvlJunior: YearLevelDescription = "Junior" Case lvlSenior: YearLevelDescription = "Senior" Case lvlGraduate: YearLevelDescription = "Graduate" Case lvlMasteral: YearLevelDescription = "Masteral" Case Else: Err.Raise 5 End Select End Property |
The addition of highest value for your enum list might confuse your user. You might want to hide this or decided not to show it from your user when they started to use your class. I common technique that you can use is by placing an underscore at the start of the enum list identifier as shown below:
Enum GenderEnum Male = 1 Female [_GENDER MAX] = Female End Enum |
The square brackets [] are necessary because, Visual Basic will complain by raising a compile error: Invalid character. Adding square brackets permit us to add an underscore ( _ )at the beginning of the enum list identifier and brought us another useful technique, you can now add space to your enum list identifier as shown above. Unfortunately, even you, the author of the class cannot see this! So you must remember this enum list identifier when you use your class, especially in the Property procedures validation code.
One last thing that I can add pertaining to enumerated type. Sometimes, you need this description to populate a control in you client form, such as ComboBox and ListBox control. One technique that I used frequently, I usually change the implementation of description property by adding an optionalByVal parameter and then use the textual description to populate the control:
' In the Student class module Public Sub LoadYearLevelDescriptionTo(ctrl As Control) Dim i As Integer ctrl.Clear For i = Freshmen To [_YEAR LEVEL MAX] ctrl.AddItem YearLevelDescription(i) Next i End Sub Property Get YearLevelDescription(Optional ByVal level As YearLevelEnum) As String Dim tempLevel As Long ' If argument level contain a value, use it in the Select Case, ' otherwise, use the Private m_YearLevel variable tempLevel = IIf(level = 0, m_YearLevel, level) Select Case tempLevel Case Freshmen: YearLevelDescription = "Freshmen" Case Sophomore: YearLevelDescription = "Sophomore" Case Junior: YearLevelDescription = "Junior" Case Senior: YearLevelDescription = "Senior" Case Graduate: YearLevelDescription = "Graduate" Case Masteral: YearLevelDescription = "Masteral" Case Else: Err.Raise 5 End Select End Property ' In your client form ' Load Year level description in ListBox Control Student.LoadYearLevelDescriptionTo List1 or ' Load Year level description in ListBox Control Student.LoadYearLevelDescriptionTo Combo1 |
See, how easy it would be in the client, I don't have to populate the List property of the Combo or ListBox control in the client form, all I have to do is to call LoadYearLevelDescriptionTo to do the work. Note, you can still use the Property YearLevelDescription without an argument:
' Return the Year Level Description of this particular Student Debug.Print Student.YearLevelDescription |
Comments