Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Terser Enum Programming with StrongEnum

0.00/5 (No votes)
11 Jan 2009 1  
Write cleaner, strongly-typed enum operations.

Introduction

Enums are great programming tools. They let you define groups of integral based constants that can be accessed elsewhere throughout your code in a strongly typed and symbolic fashion. The most obvious benefit of enums is their inherent catering to the rapid development model.

The Dilemma

The .NET library comes with a static class for enum management, System.Enum. Let's interrogate the method declarations provided by Enum:

  • object Enum.Parse(type, string)
  • object Enum.ToObject(type, object)
  • string Enum.GetName(type, object)
  • string[] Enum.GetName(type)
  • Array Enum.GetValues(type)
  • bool Enum.IsDefined(type, object)
  • Type Enum.GetUnderlyingType(type)
  • string Enum.Format(type, value, string)

Despite the wonderful functionality System.Enum provides us, it is not without its drawbacks. The first thing you should notice is that each method requires you to pass the type of enum that you wish to reference — not the enum itself, but the type of the enum. This means you have to encase the enum name within the typeof() system method. The second thing you should notice is that the Parse and ToObject methods return a type of object — this would require us to perform an explicit cast on the returned object to transform it into the designated enum object. This explicit cast resolves into a non-type-safe expression, as well as extra processing overhead.

Let's look at an example. Assume we have an enum called OrderStatus which defines four possible states: Open, Submitted, Shipped, and Invoiced.

public enum OrderStatus
{
    Open = 0,
    Submitted = 1,
    Shipped = 2,
    Invoiced = 3
}

Now, let's assume a customer wants to see all the orders that have been shipped. When the customer sends their request through, your server-side code parses the form collection if it is a POST request, or querystring if its a GET, and determines the order status filter chosen. Normally, if we want to put their choice in the form of a strongly typed enum object, we have to perform an explicit cast that looks like this:

protected void Page_Load(object sender, EventArgs e)
{
    NameValueCollection userData = Request.HttpMethod.ToUpper() == 
        "GET" ? Request.QueryString : Request.Form;
    OrderStatus orderStatus = 
        (OrderStatus)Enum.Parse(typeof(OrderStatus), userData["oStatus"]);
}

Now, this isn't too terrible looking, but imagine working with a multitude of enums within the same code block — it's going to get a little messy, and typing out typeof(MyEnum) many times over will become rather tedious and exhausting.

The Solution

The solution is incredibly simple — we will write a wrapper class that will make use of Generics to handle our enum needs in a type-safe manner. If you're not familiar with Generics, a quick explanation: they allow your classes and methods to perform operations on non-specific types, hence the term "generic". The most common use of Generics used in .NET are the Collection objects, such as List<> and Dictionary<>. After defining our Generics-supported class, all that is left to do is to implement the methods. Here is what our class should look like:

public static class StrongEnum<T>
{
    public static T Parse(string value)
    {
        return (T)Enum.Parse(typeof(T), value);
    }
    public static T Parse(string value, bool ignoreCase)
    {
        return (T)Enum.Parse(typeof(T), value, ignoreCase);
    }
    public static T ToObject(object value)
    {
        return (T)Enum.ToObject(typeof(T), value);
    }
    public static string GetName(object value)
    {
        return Enum.GetName(typeof(T), value);
    }
    public static string[] GetNames()
    {
        return Enum.GetNames(typeof(T));
    }
    public static Array GetValues()
    {
        return Enum.GetValues(typeof(T));
    }
    public static bool IsDefined(object value)
    {
        return Enum.IsDefined(typeof(T), value);
    }
    public static Type GetUnderlyingType()
    {
        return Enum.GetUnderlyingType(typeof(T));
    }
    public static string Format(object value, string format)
    {
        return Enum.Format(typeof(T), value, format);
    }
}

Now, we can write cleaner, strongly-typed enum operations:

protected void Page_Load(object sender, EventArgs e)
{
    NameValueCollection userData = Request.HttpMethod.ToUpper() == 
        "GET" ? Request.QueryString : Request.Form;
    OrderStatus orderStatus = 
        StrongEnum<OrderStatus>.Parse(userData["oStatus"]);
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here