65.9K
CodeProject is changing. Read more.
Home

Use of the Enum Description (With Special Characters) in C#

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (2 votes)

Sep 14, 2014

CPOL
viewsIcon

29489

downloadIcon

119

Can your enums have userfriendly descriptions? How to have enum values with spaces?

Introduction

Can your enums have userfriendly descriptions? How to have enum values with spaces?
What is the use of the enum description (with special characters) in C#?
How can you describe basic convertion extension methods. (Enum.ToDescription(), string.ToEnum<T>())?

Using the Code

Create your enum in your project.

public enum MyEnum1
{
    [DescriptionHelper("[Not selected]")]
    None = 0,
    Video = 1,
    Audio = 2,
    Teletext = 3,
    [DescriptionHelper("DVB Subtitles")]
    DVB_Subtitles = 4,
    ECM = 6,
    Private = 9,
    [DescriptionHelper("AC-3 Audio")]
    AC3_Audio = 10,
    [DescriptionHelper("H.264 Video")]
    H264_Video = 11,
    VBI = 12,
    [DescriptionHelper("AAC Audio")]
    AAC_Audio = 13,
}

Create your attribute class:

namespace EnumSample
{
    public class DescriptionHelperAttribute : Attribute
    {
        public DescriptionHelperAttribute(string description)
        {
            this.Description = description;
        }

        public string Description { get; protected set; }
    }
}

Then include these static extension methods in your code:

namespace EnumSample
{
    public static class MyUtility
    {
        public static T ToEnum<T>(this string s, bool ignoreCase) where T : struct
        {
            Type genericType = typeof(T);
            if (!genericType.IsEnum) return default(T);

            T response;
            if (Enum.TryParse(s, ignoreCase, out response))
            {
                return response;
            }

            Array ary = Enum.GetValues(genericType);
            foreach (T en in ary)
            {
                if ((string.Compare(en.ToString(), s, ignoreCase) == 0) ||
                    (string.Compare((en as Enum).ToDescription(), s, ignoreCase) == 0))
                {
                    return en;
                }
            }

            return default(T);
        }

        public static T ToEnum<T>(this string s) where T : struct
        {
            return s.ToEnum<T>(false);
        }

        public static string[] GetEnumDescriptions<T>() where T : struct
        {
            Type genericType = typeof(T);
            if (!genericType.IsEnum) return new string[0];

            Array ary = Enum.GetValues(genericType);
            string[] strAry = new string[ary.Length];
            int ndx = 0;
            foreach (T en in ary)
            {
                strAry[ndx++] = (en as Enum).ToDescription();
            }
            return strAry;
        }

        public static string ToDescription(this Enum en)
        {
            Type type = en.GetType();

            MemberInfo[] memInfo = type.GetMember(en.ToString());

            if (memInfo != null && memInfo.Length > 0)
            {
                object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionHelperAttribute), false);
                if (attrs != null && attrs.Length > 0)
                {
                    return ((DescriptionHelperAttribute)attrs[0]).Description;
                }
            }

            return en.ToString();
        }
    }
}

Use in the project (Testing):

MyEnum1 en;

// test1
Console.WriteLine();
Console.WriteLine("Test 1) String to enum test...");
Console.WriteLine("   (\"bla bla bla...\").ToEnum<MyEnum1>()");
en = ("bla bla bla...").ToEnum<MyEnum1>();
Console.WriteLine("   \"bla bla bla...\" was not found in MyEnum1! 
However, the result \"{0}\" will be...", default(MyEnum1));
Console.WriteLine("   Result >> Value:\"{0} - {1}\", 
Description:\"{2}\"", (int)en, en.ToString(), en.ToDescription());
Console.WriteLine();

// test2
Console.WriteLine();
Console.WriteLine("Test 2) String to enum test...");
Console.WriteLine("   (\"H.264 Video\").ToEnum<MyEnum1>()");
en = ("H.264 Video").ToEnum<MyEnum1>();
Console.WriteLine("   Result >> Value:\"{0} - {1}\", 
Description:\"{2}\"", (int)en, en.ToString(), en.ToDescription());
Console.WriteLine();

// test3
Console.WriteLine();
Console.WriteLine("Test 3) String to enum test... (Classic 'Enum.Parse' method)");
Console.WriteLine("   (MyEnum1)Enum.Parse(typeof(MyEnum1), \"H.264 Video\")");
Console.WriteLine("   \"H.264 Video\" was not found in MyEnum1! \"H264_Video\" should be...");
Console.WriteLine("   In this example, the classic 'Enum.Parse' method is useless.");
try
{
    en = (MyEnum1)Enum.Parse(typeof(MyEnum1), "H.264 Video");
}
catch (Exception ex)
{
    Console.WriteLine("   Result >> Error[{0:X}] - {1}", ex.HResult, ex.Message);
}
Console.WriteLine();

// test4
Console.WriteLine();
Console.WriteLine("Test 4) GetEnumDescriptions for 'FormWindowState'");
Console.WriteLine("   Result:");
string[] sAry = MyUtility.GetEnumDescriptions<System.Windows.Forms.FormWindowState>();
foreach (string s in sAry)
{
    Console.WriteLine("   >> {0}", s);
}
Console.WriteLine();

This will display:

Test 1) String to enum test...
   ("bla bla bla...").ToEnum<MyEnum1>()
   "bla bla bla..." was not found in MyEnum1! However, the result "None" will be...
   Result >> Value:"0 - None", Description:"[Not selected]"

Test 2) String to enum test...
   ("H.264 Video").ToEnum<MyEnum1>()
   Result >> Value:"11 - H264_Video", Description:"H.264 Video"

Test 3) String to enum test... (Classic 'Enum.Parse' method)
   (MyEnum1)Enum.Parse(typeof(MyEnum1), "H.264 Video")
   "H.264 Video" was not found in MyEnum1! "H264_Video" should be...
   In this example, the classic 'Enum.Parse' method is useless.
   Result >> Error[80070057] - Requested value 'H.264 Video' was not found.

Test 4) GetEnumDescriptions for 'FormWindowState'
   Result:
   >> Normal
   >> Minimized
   >> Maximized

Points of Interest

Why C# doesn't have extension properties? Interesting...

History

  • 14th September, 2014: Initial post