Working with Enums

Lets take time out to talk about the very tech/geeky topic of enums (enumerators). 
They can be fun, and also quite frustrating. 
 
Apologies in advance, I only do code samples in C# or C++. 
I might do Visual Basic examples, by request.
 
Here are the Australian states listed in an Enum:
 
[FlagsAttribute]
enum AustralianStates
{
    NSW = 1,
    VIC = 2,
    QLD = 4,
    SA = 8,
    WA = 16,
    TAS = 32
};
 
As every good developer should know, there is a way to convert string representations of data into other types.
This is normally achieved by the following syntax: Type.Parse() or Type.TryParse()
 
The latter, the TryParse, allows you to attempt a conversion, and to handle the ramifications if the conversion failed, as the following example demonstrates:
 
string someNumber = "42";
Int32 convertedNumber = 0;
if(Int32.TryParse(someNumber, out convertedNumber))
{
    //convertedNumber will be 42
}
else
{
    //handle the failure
}
 
This is all well and good, but Enum doesn’t have a TryParse() function.  In fact, Enum.Parse has this nasty habit of throwing exceptions if the input value isn’t valid.  This isn’t too handy, because you’ll need to manually add Try..Catch blocks around any calls to Enum.Parse().  To simplify this, I’ve come up with a class which can be very useful when working with lots of Enums.
 
First declare the class like so:
    /// <summary>
    /// This class converts values representing Enum values to their
    /// corresponding enum type or integer value
    /// </summary>
    /// <typeparam name="T">Enum Type</typeparam>
    public static class EnumConverter<T>
    {
    }
 
This class takes a type as a parameter, which lets the methods know what enum type they are going to be working with.
Next, I’m going to create a function to convert string values to their appropriate Enum values. 
 
You might wonder what the value here is.  If you’ve ever worked with ASP.net and specifically ListBoxes, you’ll know that they only store <Display Value>, <Data Value> as <String>, <String> which can be very annoying (hence, the need to convert the string back to the Enum!

        /// <summary>
        /// Convert a string to an Enum value
        /// </summary>
        /// <param name="stringToConvert">String value of an Enum value</param>
        /// <param name="success">Success or failure of the conversion as an out param</param>
        /// <returns>An enum value of type <T>, returns the default on failure</returns>
        public static T StringToEnum(string stringToConvert, out bool success)
        {
            try
            {
                // Ensure the string is valid and not empty
                if (stringToConvert != null && stringToConvert.Length > 0)
                {
                    success = true;
                    // Ignore case on the conversion
                    return (T)Enum.Parse(typeof(T), stringToConvert, true);
                }
            }
            catch(ArgumentException ex)
            {
                // Use your own Exception Management Here
            }
            catch(InvalidCastException ex)
            {
                // Use your own Exception Management Here
            }
            success = false;
            return default(T);
        }
 
Some learning opportunities here, firstly we’re going to be using an out parameter so that the calling code can determine the success or failure of the conversion.  This allows us to return an enum value regardless of the result.  Also, the "default(Type)" is very handy, especially when conversion fails.
 
You can validate the parameters any way you like, this is an example only.
 
Now you have a fine and dany way of converting a string representation, like so:
 
string stateName = "NSW";
bool success;
AustralianStates selectedState = EnumConverter<AustralianStates>.StringToEnum(stateName, out success);
if (success)
{
    //great, process the thingy
}
else
{
    //the end is nigh!
}
 
That’s wonderful, for sure.. but we know that the AustralianState.NSW is also something that can be cast, like to the integer value of 1.  So why don’t we do something to help the process of converting the string representation to the integer representation by way of an Enum?  Consider the following method:
 
        /// <summary>
        /// Convert a string to the enum int representation
        /// </summary>
        /// <param name="stringToConvert">Enum value in string format</param>
        /// <returns>int value of the enum, or Int32.MinValue on failure</returns>
        public static int StringToEnumInt(string stringToConvert)
        {
            try
            {
                // Ensure the string is valid and not empty
                if (stringToConvert != null && stringToConvert.Length > 0)
                {
                    return (int)Enum.Parse(typeof(T), stringToConvert);   
                }               
            }
            catch (ArgumentException ex)
            {
                // Use your own Exception Management Here
                HandleException(ex);               
            }
            catch(InvalidCastException ex)
            {
                // Use your own Exception Management Here
                HandleException(ex); 
            }
            // Return the equiv. of null
            return Int32.MinValue;
        }
 
Learning here that we cast the successful conversion from string to Enum to integer, using the usual refinements such as input validation.  Note that we don’t need an out parameter, we’ll let the calling code determine the success or failure by returning Int32.MinValue on failure.  Calling code should be smart enough to realize this isn’t a valid value (and if it IS a valid value, something is wrong in your design!).
 
Here is another usage example:
 
string stateName = "NSW";
Int32 stateNumber = EnumConverter<AustralianStates>.StringToEnumInt(stateName);
if (stateNumber != Int32.MinValue)
{
    //NSW is NUMBER ONE!
}
else
{
    //the end is nigh!
}
 
So, in summary, working with Enums is a necessary evil, and with a little bit of help life can be made far more simpler or less chaotic.  Enjoy and add comments or feedback as appropriate.

Leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.