The ContextSometimes, 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 ExampleSometimes 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.
enum.ToString()The enum would then be used to build the Sql by using the ToString() method of the enum:
AttributesAn 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 PatternThere 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: