Thursday, January 28, 2016

Enum extensions : Some useful methods while dealing with enums

Enums are used most widely when one wants to use discrete values for a set.
Example is Currency, say I have an enum:
 
namespace EnumUtility
{
    public enum Currency
    {
        [Description("US Dollars")]
        USD,
        [Description("Indian Rupee")]
        INR
    }
}


We can have some enum extension methods for the following items:
1. Getting description for enum
2. Getting an enum if we have the corresponding description
3. Calling "Equals()" on enum to compare it to description string
4. Calling "Equals()" on description string to compare it to enum


 
using System;
using System.ComponentModel;
using System.Linq;

namespace EnumUtility
{
    public static class EnumExtensions
    {
        /// <summary>
        /// Gets the enum desciption
        /// </summary>
        /// <param name="value">Enum value</param>
        /// <returns>Description of the enum</returns>
        public static string ToDescription(this Enum value)
        {
            var fi = value.GetType().GetField(value.ToString());
            var attributes = (DescriptionAttribute[]) fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
            return attributes.Length > 0 ? attributes[0].Description : value.ToString();
        }

        /// <summary>
        /// Can be called on string to convert it to Enum
        /// </summary>
        /// <typeparam name="T">Enum type</typeparam>
        /// <param name="description">Description attribute value</param>
        /// <returns>Returns the corresponding enum</returns>
        public static T ToEnum<T>(this string description)
        {
            var fields = typeof (T).GetFields();
            foreach (var field in from field
                in fields
                let attributes = (DescriptionAttribute[]) field.GetCustomAttributes
                    (typeof (DescriptionAttribute), false)
                where
                    attributes != null && attributes.Length > 0 &&
                    attributes[0].Description.ToLower().Equals(description.ToLower())
                select field)
            {
                return (T) Enum.Parse(typeof (T), field.Name);
            }

            throw new Exception("Description not found for the enum specified");
        }

        /// <summary>
        /// Can be called on enum to compare it to string
        /// </summary>
        /// <typeparam name="T">Enum type</typeparam>
        /// <param name="value">Enum value</param>
        /// <param name="description">String to compate to</param>
        /// <returns>Returns true if enum description matches string else returns false</returns>
        public static bool Equals<T>(this Enum value, string description)
        {
            var enumValue = description.ToEnum<T>();
            return value.Equals(enumValue);
        }

        /// <summary>
        /// Can be called on string to compare it to enum
        /// </summary>
        /// <typeparam name="T">Enum type</typeparam>
        /// <param name="description">Description string on which it is called</param>
        /// <param name="enumValue">Enum value to compare string to</param>
        /// <returns>Returns true if enum description matches string else returns false</returns>
        public static bool Equals<T>(this string description, T enumValue)
        {
            var newEnum = description.ToEnum<T>();
            return newEnum.Equals(enumValue);
        }
    }
}


And while we call these methods, code looks very clean:


 
using System;

namespace EnumUtility
{
    class Program
    {
        static void Main(string[] args)
        {
            string strUS = "US Dollars";

            // string to enum
            var currencyUS = strUS.ToEnum<Currency>();

            // enum to string
            Console.WriteLine(currencyUS.ToDescription());

            // enum compared to string
            Console.WriteLine(currencyUS.Equals<Currency>(strUS));

            // string compared to enum
            Console.WriteLine(strUS.Equals<Currency>(currencyUS));

            Console.ReadKey();
        }
    }
}