To read the article online, visit http://www.4GuysFromRolla.com/articles/042804-1.aspx

Understanding Enumerations

By Rachael Schoenbaum and Scott Mitchell


Introduction


An enumeration is a special type in the .NET Framework that is comprised of a number of named constants. While you might not have created an enumeration type yourself, you have likely used enumerations many times in day-to-day programming. For example, each item in an ASP.NET DataGrid has an ItemType property, which is of type ListItemType. ListItemType is an enumeration with values like Header, Item, AlternatingItem, Footer, and others. Too, if you've created files with the System.IO.File class you've used the FileMode and FileAccess enumerations; if you have worked with regular expressions, you've likely used the RegexOptions enumeration.

When creating your own classes and components, enumerations can be used to make your code strongly typed, which makes the code more readable and less prone to errors. Creating and using enumerations is simple, so there's no reason not to use enumerations where applicable. This article looks at how to create enumeration types, how enumerations differ from constants, how to create enumerations whose members can be combined via bit-wise operations, and how to enumerate the members of an enumeration.

Creating an Enumeration Type


An enumeration can be declared with the following syntax:

' -- VB.NET
Public Enum EnumName [As Type]
   Carriage-return delimited list of Named Constants
End Enum

// -- C#
public enum EnumName [: Type]
{
   Comma-delimited list of Named Constants
}

EnumName is the name of the enumeration type, Type is the underlying value of the enumeration, and Named Constants is a set of names and optional values corresponding to the Type. All enumerations have some core, underlying, integral value type, such as a Byte, Integer, or Long. The default underlying type is Integer.

An example of creating an enumeration can be seen below:

' -- VB.NET
Public Enum MenuItemType
   Header
   Item
   AlternatingItem
End Enum

// -- C#
public enum MenuItemType
{
   Header,
   Item,
   AlternatingItem
}

Enumerations vs. Constants


A constant is single element whose value never changes, and is declared using the following syntax:

' -- VB.NET
Public Const ConstantName As Type = Value

// -- C#
public const Type ConstantName = Value

Where ConstantName is the constant's name, Type is the type, and Value is the constant's value, which can never be changed. The benefit of using constants is that they give a name to some "magic number," which improves code readability. Unfortunately, constants don't provide strong typing. For example, imagine we had the following constants defined:

Public Const Header As Integer = 1
Public Const Item As Integer = 2
Public Const AlternatingItem As Integer = 3

Additionally, imagine that we have a method, CreateMenuItem(Integer), that takes in an Integer specifying the type of the menu item to create. This method might be called from the code like:

'Create a Header menu item...
CreateMenuItem(Header)

'Create an AlternatingItem menu item...
CreateMenuItem(AlternatingItem)

While this approach is clearly more readable that calling CreateMenuItem(1) or CreateMenuItem(3), the method allows any Integer to be passed in. That is, a call to CreateMenuItem(-1934) wouldn't cause a compile-time error (although it would likely cause a runtime error of some sort).

An enumeration, on the other hand, is strongly typed. Rather than using constants, we could use an enumeration. The CreateMenuItem() method, then, would expect an input parameter of type MenuItemType, and would be invoked using code like CreateMenuItem(MenuItemType.Header) or CreateMenuItem(MenuItemType.AlternatingItem). With this approach, a compile-time error would be noted if we attempted to call CreateMenuItem(-1934).

Enumerations Under the Covers


When compiling a project that includes enumerations, the enumeration is converted into a structure that turns each of the enumeration's named constants into an actual constant. That is, an enumeration like:

public enum MenuItemType
{
   Header,
   Item,
   AlternatingItem
}

Would get turned into the following at compile-time:

public struct MenuItemType : System.Enum
{
   public const int Header = 0;
   public const int Item = 1;
   public const int AlternatingItem = 2;
}

Notice that this structure is derived from the System.Enum class. The System.Enum class contains the base functionality for all enumerations and provides methods for accessing the individual items of an enumeration (as we'll see shortly).

Creating Enumerations Whose Members Can Be Joined via Bit-Wise Operations


What happens if your function or class needs to be passed more than one or more of your enumeration's values? For example, the RegexOptions class spells out a number of regular expression options: if the regular expression should be compiled, whether it should ignore case, whether the regular expression should have the ^ and $ symbols match on a single line, or on multiple lines, and so on. Since a regular expression might need to be configured to support more than one of these options, the bit-wise OR operator can be used. For example, to create a regular expression object that is both multiline and compiled, you'd use:

' -- VB.NET
Dim re as New Regex(pattern, _
             RegexOptions.MultiLine OR RegexOptions.Compiled)

// -- C#
Regex re = new Regex(pattern, 
             RegexOptions.MultiLine | RegExOptions.Compiled);

Notice that in VB.NET the bit-wise OR operator is OR; in C# it's |.

By default, an enumeration's members cannot be bit-wise ORed together. In order to create an enumeration that supports bit-wise operations you need to do two things:

  1. Mark the enumeration with the Flags() attribute
  2. Assign the members of the enumerations values corresponding to the powers of 2

Here's a sample of how to declare an enumeration that can support bit-wise operations:

' -- VB.NET
<Flags()> Public Enum Characteristics
	None 	   = 1
	Tall 	   = 2
	Dark 	   = 4
	Handsome   = 8
	All        = Tall Or Dark Or Handsome
End Enum 

// -- C#
[Flags()]
public enum Characteristics
{
	None 	   = 1,
	Tall 	   = 2,
	Dark 	   = 4,
	Handsome   = 8,
	All        = Tall | Dark | Handsome
}

Notice that each enumeration member has an increasing power of 2 value: 1, 2, 4, and 8. To compute the next value in the series, simply multiple the last value by 2. The reason we need the numbers to be powers of 2 is because the way integers are represented by a computer. A thorough discussion of this is beyond the scope of this article.

Imagine we had a method called MakeIdealHusband(Characteristics). This method could be called like: MakeIdealHusband(Characteristics.Tall | Characteristics.Handsome), which would create a Tall and Handsome husband.

Enumerating the Members of an Enumeration


There may be times where you need to loop through an enumeration and display either the names within the enumeration or the values. The System.Enum class contains a GetNames(Type) method that returns a string array of the enumeration members. Here's an example of how to loop through your enumeration's names:

'Loop through the enumeration members
Dim names As String() = System.Enum.GetNames(GetType(Characteristics))
For i as Integer = 0 To names.Length-1
	Response.Write(names(i))
Next		

The System.Enum class also contains a Parse(Type, String) method that can be used to get a strongly typed enumeration instance back based on a specified enumeration name. For example, to get an enumeration instance of Characteristics.Tall, we could use the following code:

'Convert string to enumeration type
Dim myMan As Characteristics = System.Enum.Parse(GetType(Characteristics), "Tall")

Conclusion


Enumerations are good for lists of things that never or very rarely change. They are not good for lists that have frequent modifications since you would have to recompile your code every time something in your enumeration changed. Your enumeration must have values with one of the following data types: Byte, Integer, Long, or Short. If you can "translate" the underlying value of your enumeration to one of these data types then that list is a good candidate for an enumeration. If your underlying values are Char or String data types, these lists are not good candidates for enumerations.

Enumerations can make your coding a lot easier to read and understand by allowing you to refer to underlying lists of constants with logical names.

Happy Programming!

  • By Rachael Schoenbaum and Scott Mitchell


    Author Bio:


    Rachael Schoenbaum is a developer specializing in ASP, ASP.NET, Visual Basic, SQL Server, XML, and related technologies. She consults for Lucidea and has been programming since 1999.

  • Article Information
    Article Title: ASP.NET.Understanding Enumerations
    Article Author: Rachael Schoenbaum
    Published Date: April 28, 2004
    Article URL: http://www.4GuysFromRolla.com/articles/042804-1.aspx


    Copyright 2017 QuinStreet Inc. All Rights Reserved.
    Legal Notices, Licensing, Permissions, Privacy Policy.
    Advertise | Newsletters | E-mail Offers