Click here to Skip to main content
15,891,253 members
Articles / Programming Languages / C#
Tip/Trick

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

Rate me:
Please Sign up or sign in to vote.
4.50/5 (2 votes)
13 Sep 2014CPOL 28.6K   118   15   3
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.

C#
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:

C#
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:

C#
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):

C#
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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Turkey Turkey
Gökhan Erdoğdu is the Software Developer for a tv channel.
His background in programming is primarily C++, but has experience in other languages.
He loves movies and music.

Comments and Discussions

 
QuestionVery nice!! Pin
_Eduardo15-Sep-14 9:31
_Eduardo15-Sep-14 9:31 
QuestionNice approach Pin
Oleg Shilo13-Sep-14 20:26
Oleg Shilo13-Sep-14 20:26 
AnswerRe: Nice approach Pin
Gokhan Erdogdu13-Sep-14 21:19
professionalGokhan Erdogdu13-Sep-14 21:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.