65.9K
CodeProject is changing. Read more.
Home

Human readable strings for enum elements

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (11 votes)

Aug 12, 2010

CPOL
viewsIcon

21392

Using enum really helps readability, but the values within the enum must understandably conform to the rules for variables names. This is fine until you need to display enum values to the user. This tip shows you how to associate and access a human readable string with each enum element.

I use a fair number of enum blocks, but I hate having matching switch statements to render them to a human readable string (or string arrays to do the same, particularly when my enum may have only six elements, with fixed values between 1 and hex 8000). So I worked this out to remove the problem and keep the descriptive text with the enum element definition. This works by using reflection to access the DescriptionAttribute which can be applied to any control, and which can also be applied to any other object - including individual variables, should you so wish. (That might be overkill, but hey! It's your software!). Declare these two static methods:
        /// <summary>
        /// Get description of a enum value
        /// See DescriptionAttribute for enum element
        /// </summary>
        /// <remarks>
        /// Returns the human readable string set as the DescriptionAttribute
        /// for an enum element.
        /// If the DescriptionAttribute has not been set, returns the enum element name
        /// </remarks>
        /// <example>
        /// public enum MyEnum
        ///    {
        ///    [DescriptionAttribute("A Human readable string")]
        ///    AMachineReadableEnum,
        ///    }
        /// ...
        ///    string s = MyEnum.AMachineReadableEnum.ToString();
        ///    s += " : " + GetDescription(MyEnum.AMachineReadableEnum);
        ///    MessageBox.Show(s);
        ///    
        /// would display "AMachineReadableEnum : A Human readable string"
        /// </example>
        /// <seealso cref="ValueOf<T>"/>
        /// <param name="value">Enum element with human readable string</param>
        /// <returns>Human readable string for enum element</returns>
        public static string GetDescription(Enum value)
            {
            // Get information on the enum element
            FieldInfo fi = value.GetType().GetField(value.ToString());
            // Get description for elum element
            DescriptionAttribute[] attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (attributes.Length > 0)
                {
                // DescriptionAttribute exists - return that
                return attributes[0].Description;
                }
            // No Description set - return enum element name
            return value.ToString();
            }
        /// <summary>
        /// Get an enum element from its human readable string.
        /// </summary>
        /// <remarks>
        /// Returns the enum element for a human readable string
        /// If the DescriptionAttribute has not been set, throws an
        /// ArgumentException
        /// </remarks>
        /// <example>
        /// public enum MyEnum
        ///    {
        ///    [DescriptionAttribute("A Human readable string")]
        ///    AMachineReadableEnum,
        ///    }
        /// ...
        ///    MyEnum me = ValueOf<MyEnum>("A Human readable string");
        ///    MyEnum me = MyEnum.AMachineReadableEnum;
        ///    
        /// would be equivelent
        /// </example>
        /// <exception cref="ArgumentException if description not found to match an enum element"
        /// <seealso cref="GetDescription"/>
        /// <typeparam name="T">Enum the element will belong to</typeparam>
        /// <param name="description">Human readable string assocuiated with enum element</param>
        /// <returns>Enum element</returns>
        public static T ValueOf<T>(string description)
            {
            Type enumType = typeof(T);
            string[] names = Enum.GetNames(enumType);
            foreach (string name in names)
                {
                if (GetDescription((Enum) Enum.Parse(enumType, name)).Equals(description, StringComparison.InvariantCultureIgnoreCase))
                    {
                    // Found it!
                    return (T) Enum.Parse(enumType, name);
                    }
                }
            // No such description in this enum
            throw new ArgumentException("The string is not a description or value of the specified enum.");
            }
Now declare your enum with the DescriptionAttribute:
        public enum MyEnum
            {
            [DescriptionAttribute("A Human readable string")]
            AMachineReadableEnum,
            [DescriptionAttribute("Another Human readable string")]
            ASecondMachineReadableEnum,
            }
And try it out:
        private void ShowItWorking()
            {
            string s = "";
            s = GetDescription(MyEnum.AMachineReadableEnum);
            s += " : " + MyEnum.AMachineReadableEnum.ToString();
            s += " : " + ValueOf<MyEnum>("a human READABLE string");
            MyEnum me = ValueOf<MyEnum>("A HUMAN readable STRING");
            s += " : " + ((int) ).ToString();
            MessageBox.Show(s);
            }