Juri Strumpflohner
Juri Strumpflohner Juri is a full stack developer and tech lead with a special passion for the web and frontend development. He creates online videos for Egghead.io, writes articles on his blog and for tech magazines, speaks at conferences and holds training workshops. Juri is also a recognized Google Developer Expert in Web Technologies

String enumerations in C#

3 min read

Enumerations are a very handy programming construct. Especially when you're developing in a larger team, you can prevent a lot of problems and possible bugs by using enum types for properties that can just have certain values. Take for instance a class property "Status". It could have several different values: just "open" and "closed" or "O" and "C" or "M" for modified and "C" for complete etc...If another developer in the team is using your class he always will have to directly go to your class in order to check the specifications (since also useful intellisense comments are missing ;) ). But if you would use enumerations he can just type and will immediately see a list of possible values. Moreover you prevent stupid bugs such as (if "C" and "M" would be the correct values) that he assigns "c" and "m" where you can sure that at some point in your app there will be a wrong comparison.

The problem however in C# is that you cannot have string enumerations although often they would be handy. I recently had the case where a possible DB value for a property is "C" for complete and "M" for modified. Furthermore these values have also to be written to a CSV file. Here a string enumeration would be great, wouldn't it? Of course you could argue to just use constant string fields, but that wouldn't be so elegant. So I decided to create one.
I searched on the web and found this solution which I've taken in part and modified to make it a bit more convenient (at least from my point of view). The strategy in this example is to make use of the System.Attribute to enhance standard enumerations.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Jsdevlib.Base
{
public class StringValueAttribute : System.Attribute
{
public StringValueAttribute(string value)
{
_Value = value;
}

private string _Value;
public string Value
{
get
{
return _Value;
}
}
}
}
Then you can create your string enumeration as needed. For instance
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Jsdevlib.Base;

namespace SimpleTests
{
public enum StringEnumeration
{
[StringValue("C")]
COMPLETE = 1,

[StringValue("M")]
MODIFIED = 2
}
}
To now retrieve the defined StringValue, the example on CodeProject used an additional utility class. I preferred to slightly change this implementation and to use the C# extension methods:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;

namespace Jsdevlib.Base
{
public static class StringEnumExtender
{
public static string StringValue(this Enum value)
{
string output = null;
Type type = value.GetType();

FieldInfo fi = type.GetField(value.ToString());
StringValueAttribute[] attrs =
fi.GetCustomAttributes(typeof(StringValueAttribute),
false) as StringValueAttribute[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
else
{
throw new InvalidOperationException("The StringValue can just be invoked on String enumerations having the '[StringValue(...)]' attribute.");
}

return output;
}
}
}
To retrieve the string value you can do now something like
StringEnumeration.COMPLETE.StringValue();
But pay attention that you have to first import the namespace in which you have definde your StringEnumExtender, because otherwise you won't see the StringValue() method. That's the drawback of extension methods.
This kind of mechanism gives you great flexibility since you can add the StringValue attribute to whatever enumeration. Btw, invoking the StringValue() on enumerations that don't define a StringValue attribute an exception will be thrown. I found that the most reasonable behavior.
Questions? Thoughts? Hit me up on Twitter
comments powered by Disqus