Click to Rate and Give Feedback
Related Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
More ...
Articles by this Author
In this installment, the author provides an enhanced implementation of the BST pattern and compares it to HTM solutions.

By Dino Esposito (July 2008)
AJAX is meant to go beyond mere partial page rendering. Find out where Dino Esposito thinks dynamic pages are headed in the future with ASP.NET AJAX.

By Dino Esposito (June 2008)
This month we begin a look at the Single Page Interface (SPI) model and some design patterns for designing AJAX applications.

By Dino Esposito (May 2008)
This month, use nested ListView controls to create hierarchical views of data and extend the eventing model of the ListView by deriving a custom ListView class.

By Dino Esposito (April 2008)
This month Dino Esposito shows you how to get Windows-style modal dialog boxes for your Web applications thanks to the Ajax Control Toolkit and some clever coding.

By Dino Esposito (Launch 2008)
This month Dino looks at AJAX control extenders again, adding more advanced features including masked editing and autocompletion.

By Dino Esposito (February 2008)
AJAX Extenders extend the behavior and features of ordinary Web controls so you can reduce postbacks and control input even better than with AJAX alone.

By Dino Esposito (January 2008)
Dino Esposito introduces the Microsoft AJAX Library and the JavaScript library for ASP.NET AJAX 1.0.

By Dino Esposito (December 2007)
More ...
Popular Articles
Learn how to create a workflow that uses InfoPath forms and other office documents for passing data to targeted activities and for use in Office documents.

By Rick Spiewak (June 2008)
Joel Pobar presents an introduction to how compilers work and how you can write your own compiler to target the .NET Framework.

By Joel Pobar (February 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Jay Flowers demonstrates how to set up and use a Continuous Integration server using both discrete tools and the more comprehensive CI Factory solution.

By Jay Flowers (March 2008)
More ...
Read the Blog
In the November issue of MSDN Magazine, Jeffrey Richter demonstrates some recent additions to the C# programming language that make working with the APM significantly easier. In the June ...
Read more!
The July 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Data Services: Develop ...
Read more!
The June 2008 issue features the first installment of a new MSDN Magazine column on software design fundamentals. We’ll discuss design patterns and principles in a manner that isn't bound to a specific tool or lifecycle methodology. In this issue, Jeremy Miller starts the Patterns in Practice column ...
Read more!
In the April 2008 issue of MSDN Magazine, Kenny Kerr introduced the Windows Imaging Component (WIC), showing you how you can use it to encode and decode different image ...
Read more!
A combination of the retained-mode graphics system and notification mechanisms such as dependency properties unleash the flexibility and power of Windows Presentation Foundation (WPF, allowing these objects to be targets of data bindings and animations. In the June 2008 issue of MSDN Magazine, Charles ...
Read more!
One problem with GUI programming in C++ is that most libraries are too low level, putting much of the burden on the programmer. In the June 2008 issue of MSDN Magazine, John Torjo introduces you eGUI++, a C++ library that gives you a ...
Read more!
More ...
Cutting Edge
All About Enums
Dino Esposito

Code download available at: CuttingEdge2006_08.exe (170 KB)
Browse the Code Online
Among the many benefits of writing magazine articles, I particularly enjoy reader feedback, especially when readers are inspired to try new things and report back with useful development tips. Recently I've had some interesting mail about enumeration types, so I've decided to talk about them here. I'll review the basics of enumeration types and their implementation in the Microsoft® .NET Framework, then look at a reader's real-world use of them.

Enumeration Essentials
An enum type, or enumeration, is a homogeneous collection of named constants. The following is the declaration of the Enum class—the root of all enumerated types:
Public MustInherit Class Enum
    Inherits ValueType
    Implements IComparable, IFormattable, IConvertible
    
Recall that .NET data types are separated into value and reference types. Whereas reference types are always allocated on the common language runtime (CLR) heap, value types are allocated on the stack or as part of a reference type. Both types ultimately derive from the base class Object. Integers, numbers, dates, Booleans, characters, and bytes are all value types, as is the System.Enum type. Only integral types can be used as the underlying type for the constants in an enum type. The full list of valid types includes Byte, SByte, Int32, UInt32, Int16, UInt16, Int64, and UInt64. Note that each programming language provides special syntax to let you declare an enumeration as a set of name/value pairs. Here's how to declare an enum in Visual Basic®:
Public Enum Categories
    Speaking
    Training
    Consulting
    Mentoring
End Enum
    
If no underlying type is explicitly declared, Int32 (Integer in Visual Basic) is used implicitly. If you want to use constants of a particular type, then you add the type name in the declaration line:
Public Enum Categories As Int64
    Speaking
    Training
    Consulting
    Mentoring
End Enum
    
Each entry in an enum represents a value of the specified (or inferred) type. By default, values are assigned consecutively starting from 0. Values can also be set explicitly, both individually and for a group of elements. The following code defines 100 as the starting point for the enumeration. The Training entry will be 101, Consulting will be 102, and so on:
Public Enum Categories As Int32
    Speaking = 100
    Training
    Consulting
    Mentoring
End Enum
    
You could also use the following:
Public Enum Categories As Int32
    Speaking 
    Training = 100
    Consulting
    Mentoring = 200
End Enum
    
In this case, Speaking is 0, Training is 100, Consulting 101, and Mentoring is 200. It is perfectly legal that each element is assigned its own value without any form of regular succession. Moreover, values associated with enum entries don't have to be unique:
Public Enum Categories As Int32
    Speaking 
    Training = 100
    Consulting
    Mentoring = 100
End Enum
    
Although an enum is declared using syntax that does not look at all object oriented, the fact is that in the .NET Framework an enum type is a regular type with its own well-defined inheritance hierarchy. Enum types are not allowed to have an object model exposing their own set of methods, properties, and events. An object model exists, however, on the base class of all enums—System.Enum. Before I examine methods on System.Enum and their usage, let's take a look at enum types under the covers.

Under the Hood
In most .NET-targeted languages, an enum is declared as a collection of named constants. It is interesting to take a look at the intermediate language (IL) code generated for a sample enum as shown in the following:
Public Enum Categories As Int32
    Speaking 
    Training  
    Consulting
    Mentoring  
End Enum
    
The disassembled IL for this snippet looks like the code in Figure 1. As you can see, this class extends System.Enum with a sequence of static public fields marked as literals. In particular, this means that compilers will transform any enum values referenced by code into raw values. For example, consider the following piece of Visual Basic code from an ASP.NET sample page:
Sub DropDownList1_SelectedIndexChanged( _
    ByVal sender As Object, ByVal e As EventArgs) _
        Handles DropDownList1.SelectedIndexChanged
    Response.Write(Categories.Mentoring)
End Sub
    
The corresponding IL is shown in Figure 2. Look carefully at line L_0006, which pushes the argument for the Response.Write value onto the evaluation stack. As you can see, the argument is an Int32 explicit value (ldc.i4 is used to load a 4-byte integer). Next, in the L_000b statement the box operation pops the argument value from the stack and replaces it with a new object that boxes the numeric value type. This is a necessary step because Response.Write requires an object as its argument.
It is also interesting to dig out some internals of the System.Enum class—the parent of all enum types.
As shown earlier, System.Enum implements three interfaces that add specific functionalities, in this case, comparison, formatting, and conversion. The IComparable interface provides a CompareTo method whereas the IFormattable interface's contribution is all in one of the overloads for the ToString method. The IConvertible interface provides a number of ToXXX methods to convert enum values into more specific, mostly numeric, types.

Working with Enum Types
The System.Enum provides a number of methods to list, parse, convert, and compare values, as you can see in Figure 3. Let's take a look at the GetValues method. It is defined as follows:
Public Shared Function GetValues(ByVal enumType As Type) As Array
Simply put, the method returns an array of objects filled with all values associated with the enum. Here's some sample code that shows how to use the GetValues method to grab the values in the Categories enum type:
Dim values As String() = [Enum].GetValues(GetType(Categories))
    
How can this work if all the compiler emits is the code in Figure 1? In other words, the compiler creates a new class that extends System.Enum and adds constant fields. Where does the GetValues method (and similarly the GetNames method) get content for the array it returns?
If you look under the hood of the System.Enum class using a decompiler or disassembler, you'll see that the class internally makes use of a Hashtable synchronized for access. The Hashtable is initialized in the static constructor of the Enum class. Also known as a type initializer, a static constructor is a method that the CLR invokes automatically (if any is defined on a type) to initialize a type. A type initializer in Microsoft intermediate language (MSIL) is a static method named .cctor. Type initializers are useful to ensure that some static code executes before a class is instantiated. The following is Visual Basic pseudocode for the relevant portion of the .cctor method of System.Enum:
Shared Sub New()
   ...
       Enum.fieldInfoHash = _
           Hashtable.Synchronized(New Hashtable)
End Sub
    
When will the fieldInfoHash internal member be accessed? It is used by most of the methods on System.Enum, that is Parse, GetNames, GetValues, and IsDefined, plus a few other internal and private methods. GetValues, for example, instantiates an array to return to callers and populates it with data from fieldInfoHash.
The Hashtable is populated on-demand through reflection with the values of all the named constants that form the enum. It is worth noting that the GetHashEntry method takes a type parameter; the Hashtable contains information for all enum types being used in the application. The cost of the reflection to populate the Hashtable for a particular enumeration is paid only once per application; any successive access is to cached data. All static methods on the System.Enum class consume cached data with no significant performance costs.

Binding Enum Values to the UI
The main purpose of GetValues is to provide the contents of the enum type in a bindable form. In both ASP.NET and Windows® Forms, data can be bound to user interface controls if it's supplied in collection containers. There might be circumstances in which showing the contents of an enum through a data-bound control is desirable. This is the case, for example, when you're building middle-tier objects and need to strongly identify a particular category of values whose natural type—be it Integer, Byte, or Long—is too generic for the role the data plays in the context of the application. Enumerations make code easier to read and write and easier to understand and debug. A named constant is far more readable than a number. In addition, enums promote strongly typed programming. If the parameter of a method is defined as being of type Categories, for instance, you have to either pass a value from Categories or explicitly throw away some type safety by casting a valid integral value to the Categories type before supplying it to the method.
A set of options and settings for a number of components can be effectively expressed using enum values. Where users can configure the behavior of these components you might want to show options through data-bound controls such as a dropdown list or a group of checkboxes.
The following ASP.NET code shows how to bind the names of the values in an enum to a dropdown list:
DropDownList1.DataSource = _
    [Enum].GetNames(GetType(Categories))
DropDownList1.DataBind()
    
The dropdown list displays the names of the elements and returns the same names when users make their selection. Take a look at the following code:
Response.Write(DropDownList1.SelectedValue)
    
If the dropdown list is bound to an enum type (see Figure 4), the preceding code fragment returns the displayed string regardless of the value of each entry. It would be nice to have the ability to display symbolic names in a data-bound control and return real numeric values when a selection is made. For this to happen, some changes must be made on the control to specialize it for an enum.
Figure 4 Enum in Dropdown 
To map a symbolic name to an enumerated value, you use the Parse method, as in the following:
Dim c As Categories = _
    [Enum].Parse(GetType(Categories), "Mentoring")
    
To bind the contents of an enum type to a control, you need to transform those contents into a collection which is then bound. Likewise, to retrieve a selection from the same control, you need an additional parse step. Both actions can be incorporated into a new control. Let's see how to specialize a data-bound control (a dropdown list, for example) to work with enums declaratively.

A Custom Dropdown List Control
Figure 5 lists the code for a new dropdown list control that is built to work with enums. The idea is that the new control takes an enum type name and automatically sets the data source of the control to the contents of the enum type. The new control introduces two new properties to express the type of the bound enum: DataSourceType and DataSourceTypeName. The two properties refer to the same piece of information—the enum type name—in two distinct forms—object and string.
Let's examine the set method of the DataSourceTypeName string property:
Set(ByVal value As String)
    ViewState("DataSourceTypeName") = value
    Dim t As Type = Type.GetType(value)
    If t.BaseType Is GetType(System.Enum) Then
        DataSource = [Enum].GetNames(t)
    End If
End Set
    
If the Type object that corresponds to the specified string derives from System.Enum, the DataSource property of the control is automatically set to the array returned by the GetNames method. The DataBind method is not invoked, so you still need to trigger the data-binding operation programmatically when it is more convenient to your code.
As the code demonstrates, by associating a type name (or an equivalent Type object) with the dropdown control you are laying the groundwork for flowing the named constants of the enum into the control via binding. To illustrate the retrieving process, let's examine the code for the SelectedEnumValue property by taking a look at Figure 6.
The get accessor of the property SelectedEnumValue is a read-only property. First it ensures that either DataSourceType or DataSourceTypeName is defined and can provide type information. Next, it parses the string returned by the SelectedValue property of the base dropdown list class and obtains an enumerated value. Finally, the value returned by the property is the result of the ToObject method on the enumerated value.
Putting it all together, with the new dropdown list control in Figure 5 you can write ASP.NET pages like so:
<%@ Register Namespace="MsdnMag.CuttingEdge" TagPrefix="msdn" %>
...
<msdn:EnumDropDownList ID="DropDownList1" runat="server" 
   AutoPostBack="true"
   DataSourceTypeName="Categories">
</x:EnumDropDownList>
    
The SelectedIndexChanged event on the dropdown list can be used to capture the value of the new SelectedEnumValue property, as shown here:
Protected Sub DropDownList1_SelectedIndexChanged( _
    ByVal sender As Object, ByVal e As EventArgs) _
        Handles DropDownList1.SelectedIndexChanged
    Response.Write(DirectCast(DropDownList1.SelectedEnumValue, Int32))
End Sub
    
The sample EnumDropDownList control provides the same capabilities as the parent dropdown plus the ability to bind directly to enums. A similar mechanism can be easily built for Windows Forms applications extending the combobox control.

Formatting Enum Values
The ToObject method takes type information and a symbolic constant and returns the corresponding value. The Format method does something similar except that it converts the specified constant of the enum into an equivalent string or numeric representation:
Dim cat As Categories = Categories.Training
Response.Write([Enum].Format(GetType(Categories), cat, outputFormat))
    
The Format method supports a few predefined output formats, each identified with a letter. The outputFormat variable in the preceding code snippet can take any of the following values: F, D, X, or G. The X format represents the value as a hexadecimal value without the leading 0x. The D format renders the value as a decimal value. The F format toggles between the symbolic and numeric representation of an enum value. For example, if you call Format and specify the value as, say, Training, it will return the numeric value of the element. If you call Format on a numeric value, the output string contains the symbolic name. The G format works like F except that it also fully supports enum types with the Flags attribute.

The Flags Attribute
The Flags attribute indicates that the elements of an enumeration can be composed in a bitwise manner:
<Flags> _
Public Enum Categories As Int32
    Speaking = 1
    Training = 2
    Consulting = 4
    Mentoring = 8
    All = Speaking Or Training Or Consulting Or Mentoring
End Enum
    
When the Flags attribute is used, you can use the Or operator in Visual Basic (and the | operator in C#) to combine values to form new valid values of the same enum type. In this case, it is essential that you give explicit values to enum values as unique powers of two. It is interesting to note that when Flags is specified, Parse and Format methods feature advanced capabilities. For example, the following code returns a comma-separated string of constants: "Speaking, Training, Consulting".
Response.Write([Enum].Format(GetType(Categories), 7, "g"))
Likewise, the Parse method can successfully parse a comma-separated string like the one just shown into the proper numeric value. This is a very powerful feature, especially when you're reading options from the configuration file of an application:
<appSettings>
   <add key="Categories" value="Speaking, Training" />
</appSettings>
You use the ConfigurationManager class to retrieve the string from the configuration file and then convert it into the format that is more convenient:
Dim o As Object = [Enum].Parse(GetType(MyCategories), _
    ConfigurationManager.AppSettings("Categories"))
Dim n As Int32 = DirectCast(o, Int32)
Response.Write(n)
The preceding code reads back the configuration section and converts to an integer.

Enum Values in a Data Access Layer
Now that I've recapped the basics of enum types and investigated some of the internals, I'd like to turn to the set of questions asked by one of my readers. The reader built a relatively simple data access layer; for the most part, he relied on table adapters. However, he extended the set of classes generated by the Visual Studio® 2005 data designer with some helper classes to better describe some of the logical entities and relationships in the problem domain. One of the entities—I'll call it the Document—required a member describing the source of the contained data. In the example, the member can take a value from a short list of fixed values. The reader defined an enum like this:
Public Enum SourceType As Short
    Unknown = -1
    Xml = 1 
    SqlDatabase  
    JetDatabase
    RawText
End Enum
He wrote ADO.NET code to save and restore these values to a SQL Server database and was looking for an effective way to list available options from within ASP.NET pages and Windows Forms. The GetValues and GetNames methods, along with the Parse method, were obvious choices. I suggested the creation of a couple of custom controls (like the aforementioned EnumDropDownList) to make the writing of the user interface simpler. All in all, is using an enum in a similar situation a good choice?
I see two main disadvantages to using enum types: maintainability and localization. Incorporating the values of the enum types into the user interface was child's play for the reader and made the involved component neater, easier to read, even more elegant, and extremely cheap to implement. The rub here is that an enum type bound to UI controls exposes internal information—specifically, type information—to the presentation layer. A dropdown list like the one in Figure 4 shows off type information. If you modify the type by renaming one of the members, for example, you have to recompile the assembly in which the type is defined.
As an alternative you could create an entity class for the information and supply a data provider component that wraps the behavior of the entity. This provider component would take care of exposing the contents of the entity through a set of contracted methods. Where does the provider get its data? Typically, entity information is obtained from database tables. Changes to the information involve the database administrator and don't require a compile step. In the database table, you could provide for an ID and DisplayName pair of columns for a neat separation between UI, presentation data, and type information, and still maintain a strongly typed programming style. If you're familiar with the Northwind database, you know that it features a Categories and Products table. Each product is bound to a category via a classic foreign-key relationship. Admittedly, there's a bit of abstraction in this solution that many real programmers tend to skip as an unneeded layer of complexity. The reader decided that in his own solution with a lot of table adapters and DataSet, a data-mapper layer would have been too much even if limited to a couple of entities. So he opted for enum types and actually delivered the application.
A few months later, his boss asked him to provide a localized version of the application. How can you localize an enum type? Well, normally you won't need to. Enum types are numeric values and numbers look the same in many cultures. But this is not the case if you use the symbolic name of the constant in the user interface. In that case, you'd have to redefine the type!
To make a long story short, a choice made to simplify and speed up coding proved later to be patently wrong. There is a lesson to be learned here: enum types are a powerful tool, but they are not appropriate for every situation.

Send your questions and comments for Dino to cutting@microsoft.com.


Dino Esposito is a mentor at Solid Quality Learning and the author of Programming Microsoft ASP.NET 2.0 (Microsoft Press, 2005). Based in Italy, Dino is a frequent speaker at industry events worldwide. Get in touch with Dino atcutting@microsoft.com or join the blog at weblogs.asp.net/despos.

Page view tracker