Saturday, 30 June 2012

Type Safe Enum Pattern in C#

The Context

Sometimes, a feature of the C# language just isn't quite enough to do the job you'd like it to. An alternative view is that it wasn't designed to do that; I hear what you're saying, but let's ignore that for the time being. The built in structure to restrict a list of items to a known set is the enumeration. This is designed to provide a programmer with a choice of strongly named constants, that each map to a numeric value.

The Example

Sometimes the list of items that is needed is not numeric, but a string; take for example the following data structure, which maps a list of features available on to a list of cars.

Given feature.Id is calculated by the database on entry (Sql Server 'IDENTITY', MySql 'AUTO_INCREMENT'), the Id of the feature can't be relied on to be constant across different installations, so the Name column needs to be used as the identifying property.
When searching for whether a particular feature is available on a car, some SQL needs to be constructed, to query the table, e.g.

In order to constrain the list of features available to a developer, the usual approach would be to create an enum containing the features available


The enum would then be used to build the Sql by using the ToString() method of the enum:
This method will rely on the enum being named identically to the database value, and will not allow spaces in the name, so "Air Conditioning" and "Heated Seats" are not valid names.


An alternative method is to create a custom attribute for the enum to define the database name:
This allows the "name" of the feature to be specified, with the added advantage that the attribute name does not need to match the enum name. However, there is extra plumbing required to reflect the attribute value at runtime:

The Type Safe Enum Pattern

There is an alternative to the above solutions, and it is to effectively roll your own enum. I'm not going to pretend any of this was my idea, I believe there are examples of it in the hieroglyphics from Tutankhamen's tomb.
The best way to describe the pattern is to show an example:

This gives you a class that has static properties with a type of that class... ouch. But it means that the usage of the class is almost exactly the same as the usage of an enum, but without the confusion of an enum being intrinsically a number:

No comments:

Post a Comment