Question

Does anyone know how to transform a enum value to a human readable value?

For example:

ThisIsValueA should be "This is Value A".

Was it helpful?

Solution

Converting this from a vb code snippet that a certain Ian Horwill left at a blog post long ago... i've since used this in production successfully.

    /// <summary>
    /// Add spaces to separate the capitalized words in the string, 
    /// i.e. insert a space before each uppercase letter that is 
    /// either preceded by a lowercase letter or followed by a 
    /// lowercase letter (but not for the first char in string). 
    /// This keeps groups of uppercase letters - e.g. acronyms - together.
    /// </summary>
    /// <param name="pascalCaseString">A string in PascalCase</param>
    /// <returns></returns>
    public static string Wordify(string pascalCaseString)
    {            
        Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
        return r.Replace(pascalCaseString, " ${x}");
    }

(requires, 'using System.Text.RegularExpressions;')

Thus:

Console.WriteLine(Wordify(ThisIsValueA.ToString()));

Would return,

"This Is Value A".

It's much simpler, and less redundant than providing Description attributes.

Attributes are useful here only if you need to provide a layer of indirection (which the question didn't ask for).

OTHER TIPS

The .ToString on Enums is relatively slow in C#, comparable with GetType().Name (it might even use that under the covers).

If your solution needs to be very quick or highly efficient you may be best of caching your conversions in a static dictionary, and looking them up from there.


A small adaptation of @Leon's code to take advantage of C#3. This does make sense as an extension of enums - you could limit this to the specific type if you didn't want to clutter up all of them.

public static string Wordify(this Enum input)
{            
    Regex r = new Regex("(?<=[a-z])(?<x>[A-Z])|(?<=.)(?<x>[A-Z])(?=[a-z])");
    return r.Replace( input.ToString() , " ${x}");
}

//then your calling syntax is down to:
MyEnum.ThisIsA.Wordify();

Most examples of this that I've seen involve marking your enum values up with [Description] attributes and using reflection to do the "conversion" between the value and the description. Here's an old blog post about it:

http://geekswithblogs.net/rakker/archive/2006/05/19/78952.aspx

You can inherit from the "Attribute" class of System.Reflection to create your own "Description" class. Like this (from here):

using System;
using System.Reflection;
namespace FunWithEnum
{
    enum Coolness : byte
    {
        [Description("Not so cool")]
        NotSoCool = 5,
        Cool, // since description same as ToString no attr are used
        [Description("Very cool")]
        VeryCool = NotSoCool + 7,
        [Description("Super cool")]
        SuperCool
    }
    class Description : Attribute
    {
        public string Text;
        public Description(string text)
        {
            Text = text;
        }
    }
    class Program
    {
        static string GetDescription(Enum en)
        {
            Type type = en.GetType();
            MemberInfo[] memInfo = type.GetMember(en.ToString());
            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);
                if (attrs != null && attrs.Length > 0)
                    return ((Description)attrs[0]).Text;
            }
            return en.ToString();
        }
        static void Main(string[] args)
        {
            Coolness coolType1 = Coolness.Cool;
            Coolness coolType2 = Coolness.NotSoCool;
            Console.WriteLine(GetDescription(coolType1));
            Console.WriteLine(GetDescription(coolType2));
        }
    }
}

You can also take a look at this article: http://www.codeproject.com/KB/cs/enumdatabinding.aspx

It's specifically about data binding, but shows how to use an attribute to decorate the enum values and provides a "GetDescription" method to retrieve the text of the attribute. The problem with using the built-in description attribute is that there are other uses/users of that attribute so there is a possibility that the description appears where you don't want it to. The custom attribute solves that issue.

I found it best to define your enum values with an under score so ThisIsValueA would be This_Is_Value_A then you can just do a enumValue.toString().Replace("_"," ") where enumValue is your varible.

An alternative to adding Description attributes to each enumeration is to create an extension method. To re-use Adam's "Coolness" enum:

public enum Coolness
{
    NotSoCool,
    Cool,
    VeryCool,
    SuperCool
}

public static class CoolnessExtensions
{
    public static string ToString(this Coolness coolness)
    {
        switch (coolness)
        {
            case Coolness.NotSoCool:
                return "Not so cool";
            case Coolness.Cool:
                return "Cool";
            case Coolness.VeryCool:
                return "Very cool";
            case Coolness.SuperCool:
                return Properties.Settings.Default["SuperCoolDescription"].ToString();
            default:
                throw new ArgumentException("Unknown amount of coolness", nameof(coolness));
        }
    }
}

Although this means that the descriptions are further away from the actual values, it allows you to use localisation to print different strings for each language, such as in my VeryCool example.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top