C#: Enums and String Values
One of the biggest things that I've had a problem with C# is its complete, utter lack of string value enumerations. Enums provide strongly typed domain values that make programming easier to manage. However, since you can't include characters like wildcards, spaces, etc., this means that making a human readable enum a nearly impossible task. Until now. This takes a little more heavy lifting than I come to expect with the .Net framework, but is a relatively easy fix for what you get in return. This is broken into two parts:
- Create the String value for the enum.
- Get the value out.
First things first, how to create a string value enum. To do this we need to import the System.Reflection
and System.ComponentModel
into the class and to create a new enum as follows:
public enum IceCream
{
[DescriptionAttribute("Chocolate Chip")]ChocolateChip,
[DescriptionAttribute("Rocky Road")]RockyRoad,
Vanilla
}
As you can see we define the enum just like we normally do, except we take advantage of C#'s DescriptionAttribute
class. What this does is allows us to bind a string attribute to the enum which normally only accepts numerical type data. Unlike other methods to do this, we don't break the enum paradigm. If I had my druthers I would have liked to inherit from the Enum class itself, but that's not possible.
So, now that we've created our enum, how do we retrieve that value? Next we create another class as outlined below:
public class EnumUtils
{
public static string stringValueOf(Enum value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
else
{
return value.ToString();
}
}
public static object enumValueOf(string value, Type enumType)
{
string[] names = Enum.GetNames(enumType);
foreach (string name in names)
{
if (stringValueOf((Enum)Enum.Parse(enumType, name)).Equals(value))
{
return Enum.Parse(enumType, name);
}
}
throw new ArgumentException("The string is not a description or value of the specified enum.");
}
}
What we do in the first method is use reflection to access the DescriptionAttribute that we created when we constructed the enum. If the enum value doesn't have a DescriptionAttribute associated with it, we return the ToString() value of the enum itself. That way, enums like 'Vanilla' get returned as "Vanilla" instead of null.
The second method enumValueOf address the need to go from the string value to the enum itself. This uses the Enum static methods to compare the string value to the list of enum values. While this particular could be further optimized with caching, this sets up a basic, but useful string value enumeration.
Enjoy!