Enum, 0 and Nothing

26 Jul 2005

One feature that I like a lot in the .NET framework is Enumerations. They can be used for all sorts of things; indicating a variation of an object, encapsulating a static list of values that a certain field or property can hold and more. Since all Enumerations are based on Integer-related datatypes (such as Byte, Long or Integer), so the individual enumeration values will in the end be an integral numeric value. So far, so god. Let's make an enumeration (I'll use VB.NET syntax):

Private Enum UIState
    Resting
    Working
End Enum

This is a very simple enumeration for indicating the current state of the GUI. Either it's Resting, waiting for user input, or it's working, so the user will wait. Actually, this enumeration is so simple that it could have been replaced by a Boolean, but for the sake of the discussion, I'll disregard from that.

Since I have not declared a type for the enumeration, it will be Integer, and as I have not assigned values to the enumeration members, they will automatically get a sequence of values starting at 0 (0, 1, 2, ...). Great! Seems simple enough. Now, I want to write a function which will set the correct properties of my controls depending on the current state. If the method is called with no state passed, I want it to default to Working:

Private Sub SetControlState(state As UIState)
    Dim vLocalState As UIState
    If  state = Nothing Then
        vLocalState = UIState.Working
    Else
        vLocalState = state
    End If
    ' Here comes the code to set state of controls...
    ' ...
End Function

Now comes the funny part. If I make the call SetControlState(Nothing), I will assume that it uses the UIState.Working value to carry out its operations. It won't. Instead it will happily use UIState.Resting. Why is that? The answer is; because the values of UIState are of a value type. In the .NET world of integral values, 0 and Nothing (or null in C#) are the same. So the following two lines of code will give the same result:

If state = UIState.Resting Then
    ...
If state = Nothing Then
    ...

Since UIState.Resting = 0, and Nothing = 0, they are the same. How do we get around this? It's easy: always assign explicit values to your enumeration members, and don't use 0:

Private Enum UIState
    Resting = 1
    Working = 2
End Enum

Now the SetControlState method will correctly default to Working if Nothing is passed as parameter.

There is one thing to keep in mind if you use enumerations like this, though. If you make a user control (or any other type that will be used in a design time environment), and that type has a public property that is of an enumeration type that does not have a member with the value of 0, you will get some error messages from the development environment. By default it will try to assign 0 to the property, which is an invalid value. There are two ways around this; either make sure to define a valid default value for that property (using the DefaultValue attribute) or create a member called "NotSet" (or "None" or something similar) and give it the value 0.

Bookmark and Share