You want to use enums and named constants in an array as indexes. You can use arrays that are accessed with enumerated named constants. This technique is ideal for some kinds of data such as numeric data that helps you monitor processes easily. Here we look at how you can index arrays using enumerated types in the C# programming language, first seeing an example and its output, and then discussing some important aspects of enum arrays.
First, in the C# language enum values are actually integral types, meaning they are usually Int32 values. Just like any integer value, you can access an array with their values. Enum values are automatically ordered starting with zero, based on their textual order. In the following example, the first enum named constant in MessageType is zero, and the second is one.
~~~ Program that uses enum indexes (C#) ~~~
using System;
/// <summary>
/// Enum values used to index array.
/// </summary>
enum MessageType
{
Startup,
Shutdown,
Reload,
Refresh,
Sleep,
Error,
Max
}
/// <summary>
/// Contains array of elements indexed by enums.
/// </summary>
static class Message
{
/// <summary>
/// Contains one element per enum.
/// </summary>
public static int[] _array = new int[(int)MessageType.Max];
}
class Program
{
static void Main()
{
// Assign an element using enum index.
Message._array[(int)MessageType.Startup] = 3;
// Assign an element.
Message._array[(int)MessageType.Error] = -100;
// Increment an element using enum index.
Message._array[(int)MessageType.Refresh]++;
// Decrement an element using enum index.
Message._array[(int)MessageType.Refresh]--;
// Preincrement and assign an element.
int value = ++Message._array[(int)MessageType.Shutdown];
// Loop through enums.
for (MessageType type = MessageType.Startup; type < MessageType.Max; type++)
{
Console.Write(type);
Console.Write(' ');
Console.WriteLine(Message._array[(int)type]);
}
}
}
~~~ Output of the program ~~~
Startup 3
Shutdown 1
Reload 0
Refresh 0
Sleep 0
Error -100Overview of program text. This program has three main parts. First, you see the MessageType enumeration, which is just a series of integer values you can access with the strongly-typed named constants. The second part is a class containing the array we will access with those constants. The third part is the Main method, which demonstrates how the enum and array works.
MessageType enum. The MessageType enumeration contains seven named constants. It is usually best to start with a None constant and then end with a Length constant. This example enum has a Max constant on the end that will store the count of the named constants. This is needed for allocating the array.
Message class. The class shown next is the Message class and it contains an array. The array is initialized to contain the number of elements that is equal to the count of named constants in the MessageType enum. This makes it easy to use the named constants to access parts of this array. It is public and static because it is a global variable array that can be used throughout the program.
Description of Main entry point. The Main entry point is where control flow begins in the program. The statements in the method's body assign, increment, decrement, and preincrement elements in the array using the MessageType enumeration's named constants. This changes the values in the public static array. The enumeration values are treated as integers by using explicit casts. For example, MessageType.Startup is 0 and MessageType.Error is 5.
Looping through enums. Finally, the example shows how you can loop through enumerated values. The for loop here goes through each enum except the last one and displays the string representation and then the value of the array element corresponding to it.
This code basically shows how you can use a global variable array in a reasonable way. When using global variables, you should use accessor routines, which provide a level of abstraction on your usage of the globals. The example does not show any access routines, but you could easily implement some on the Message class. It would be best to even remove the public accessibility domain modifier from the array. You can find excellent tips on access routines in Code Complete. (Code Complete, 2nd Edition - Steve McConnell; page 340)
(See Code Complete [Book Review].)
The array element indexing show in the example is used in many important programs. It is particularly useful for collecting runtime statistics for release mode debugging support. For example, you can track what methods are executed and how often in your ASP.NET website. Software such as Google Chrome collects hundreds of statistics during runtime.
The code shown in this article is vulnerable to exceptions during runtime. You can use access routines to mitigate this possibility. For critical variables that must be statics, it is still best to use separate variables at the type level. Because the array lookup must occur before getting the value, the code here is slightly slower in many cases as well. On the other hand, it forces the variable to stored together, which will provide better locality of reference.
Here we saw how you can access array elements using enumerated types in the C# programming language. We looked at an example of code that looks up elements this way and then saw its output. We next discussed some problems with this code and also some of its benefits. Many programs use arrays in this way to collect and store numeric values to simplify runtime.