Introduction to Class Programming Part II

Enumerated Properties

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     

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“C++ : Where friends have access to your private members.” - Gavin Russell Baker