The Enum<T> also provides a way to convert a string to an enum element, which is convenient when
you're doing things like reading configuration files that use enum values. This
conversion is done with a staticValueOf(string) method:

We sometimes need to be able to use the enum as an array index,
so an Ordinal() method (that returns
a unique integer value for each enum element) is provided for that purpose.
Ordinal values start at 0, and are assigned in declaration order:

The only thing that's missing is a way to do a switch. The Ordinal()
method isn't useful for that because the case values have to be constants, so it's not really
a solvable problem.
In a pinch, you can simulate a switch with a sequence of if/else statements that don't have
that restriction.

Implementing EnumBase<T>

The real work is all in the EnumBase<T> class, so let's look at that (This class is in the same
listings file as the eariler NUnit tests). Starting at the top with a few field declarations:

The field name and the ordinal are self-explanatory.
Bear in mind that this class defines the fields and methods of each enum element, so every element carries
around it's own field name and ordinal value.
We'll look at how they're initialized shortly.

The enumElements field requires quite a bit more explanation. First, I'm using the
IReadOnlyDictionary interface and
ReadOnlyDictionary class. These are new to .NET, and aren't available if you're using Visual Studio 10.
I've provided versions in the listings file in case you need them (simple wrappers around Dictionary that
throw exceptions if you try to modify the contents).

The main issue is the use of a Lazy<T>.
This class just wraps a reference to another class. It calls the lambda that's passed in as an argument
the first time you access enumElments.Value, returning a reference to the encapsulated object.
Think of the lambda as a kind of factory method: The factory is invoked at first access to create
the object. The factory method is fully thread safe, so you don't have to worry about two threads
accessing Value simultaneously.

The enumElements dictionary holds all the enum elements and is indexed by the name of the element represented as a string.
The problem that the Lazy<T> is solving is order of initialization. enumElements is a superclass field, but it holds
a list of objects that are created by the subclass. C# does define an order of initialization, but it turns out that this order
is not always honored by debuggers. The best solution is to hold off on initializing the list until after all construction
(both super- and subclass, both static and instance) is completed. The object must be completely initialized, of course,
when we call a method that accesses enumElements, so that's a safe time to initialize.

Looking at the actual initialization code, I'm getting the names of the enum elements out of the subclass using the
magic of introspection. The code is simplified, considerably, by the generic argument T, which represents the subclass.
Taking IDictionary<string, T> dict = new Dictionary<string, T>(); as an example. Given

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!