Three Methods to Convert Strings into Enums in C#

ivankahl

Ivan Kahl

Posted on December 6, 2020

Three Methods to Convert Strings into Enums in C#

I recently had to solve the problem of converting strings into enums in C#. There are a few different solutions you can implement depending on your requirements. This article aims to show you some of these solutions and when to use each one.

Method 1: Enum.Parse Method

This is probably one of the simplest methods as it is built into .NET. It allows you to convert a string into an enum by matching the given string to the enum item with the same name and then returning that enum item.

It's important to note that the string comparison is case-sensitive by default but can be configured to be case-insensitive.

Program.cs

using System;

namespace ConvertStringToEnum
{
    enum Priority
    {
        High = 1,
        Medium = 2,
        Low = 3
    }

    class Program
    {
        static void Main(string[] args)
        {
            var result = Enum.Parse<Priority>("High");
            // Match using case-insensitive string comparison
            var result2 = Enum.Parse<Priority>("low", true);

            Console.WriteLine($"result: {result}");
            Console.WriteLine($"result2: {result2}");

            // Try find an enum that doesn't exist
            try
            {
                var result3 = Enum.Parse<Priority>("mid");
                Console.WriteLine($"result3: {result3}");
            }
            catch (ArgumentException e)
            {
                Console.WriteLine($"Could not parse enum from string. Exception: {e}");
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Advantages

  • Easy to remember and read
  • Can use case-insensitive comparison
  • Can return a typed enum using the generic type overload ( Enum.Parse<TEnum>() )

Disadvantages

  • Need to implement error handling with try-catch (catch the ArgumentException exception for when the specified enum item is not found)
  • The string has to match the enum's item name (i.e. you cannot match on description or other attributes in the enum)

Method 2: Enum.TryParse Method

This method works the same as the previous method: it retrieves the enum item with the same name as the specified string. However, this method also takes care of error-handling for us making it much simpler to use.

Just like the previous method, this method is also case-sensitive by default but can be configured to be case-insensitive.

Program.cs

using System;

namespace ConvertStringToEnum
{
    enum Priority
    {
        High = 1,
        Medium = 2,
        Low = 3
    }

    class Program
    {
        static void Main(string[] args)
        {
            Priority result;
            Enum.TryParse("High", out result);

            // Match using case-insensitive string comparison. We are also
            // using C# 7.0's parameter type inlining feature here.
            Enum.TryParse<Priority>("low", true, out Priority result2);

            Console.WriteLine($"result: {result}");
            Console.WriteLine($"result2: {result2}");

            // Try find an enum that doesn't exist
            if (Enum.TryParse<Priority>("mid", out Priority result3))
                Console.WriteLine($"result3: {result3}");
            else
                Console.WriteLine("Could not find the specified enum item :(");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Advantages

  • Easy to remember and read
  • Can use case-insensitive comparison
  • Can return a typed enum using the generic type overload ( Enum.TryParse<TEnum>() )
  • Manages error-handling and returns a bool indicating if the conversion was successful or not.

Disadvantages

  • The string has to match the enum item's name (i.e. you cannot match on description or other attributes in the enum)

Method 3: Using Reflection

This method is by far the most complex but gives us a lot more control over retrieving the correct enum item based on the given string. We will use reflection to retrieve the correct enum item using the DescriptionAttribute assigned to each enum item. This attribute is powerful because our string does not have to match the name of the enum item exactly.

In the example below, we are implementing reflection inside a static method so that we can then call this static method to retrieve the correct enum item based on the given string.

EnumReflection.cs

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace ConvertStringToEnum
{
    public static class EnumReflection
    {
        /// <summary>
        /// Retrieves an enum item from a specified string by matching the string to the DescriptionAttribute
        /// elements assigned to each enum item
        /// </summary>
        /// <typeparam name="TEnum">The enum type that should be returned</typeparam>
        /// <param name="description">The description that should be searched</param>
        /// <param name="ignoreCase">Whether string comparison of descriptions should be case-sensitive or not</param>
        /// <returns>The matched enum item</returns>
        /// <exception cref="ArgumentException">Thrown if no enum item could be found with the corresponding description</exception>
        public static TEnum GetEnumByDescription<TEnum>(string description, bool ignoreCase = false) 
            // Add a condition to the generic type
            where TEnum : Enum
        {
            // Loop through all the items in the specified enum
            foreach (var item in typeof(TEnum).GetFields())
            {
                // Check to see if the enum item has a description attribute
                if (Attribute.GetCustomAttribute(item, typeof(DescriptionAttribute)) is
                    DescriptionAttribute attribute)
                {
                    // If the enum item has a description attribute, then check if
                    // the description matches the given description parameter
                    if (string.Equals(attribute.Description, description,
                        ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal))
                        return (TEnum) item.GetValue(null);
                }
            }

            // If no enum item was found with the specified description, throw an
            // exception
            throw new ArgumentException($"Enum item with description \"{description}\" could not be found",
                nameof(description));
        }

        /// <summary>
        /// Tries to retrieve an enum item from the specified string by matching the string to the DescriptionAttribute
        /// elements assigned to each enum item
        /// </summary>
        /// <typeparam name="TEnum">The enum type that should be retrieved</typeparam>
        /// <param name="description">The description that should be searched</param>
        /// <param name="ignoreCase">Whether string comparison of descriptions should be case-sensitive or not</param>
        /// <param name="result">The matched enum item if it was found</param>
        /// <returns>Whether or not the enum item was found or not</returns>
        public static bool TryGetEnumByDescription<TEnum>(string description, bool ignoreCase, out TEnum result)
            where TEnum : Enum
        {
            try
            {
                // We try to get the enum using our original method
                result = GetEnumByDescription<TEnum>(description, ignoreCase);
                return true;
            }
            catch (ArgumentException)
            {
                // If we cannot retrieve the enum item, set it to the default and
                // return false
                result = default(TEnum);
                return false;
            }
        }

        /// <summary>
        /// Tries to retrieve an enum item from the specified string by matching the string to the DescriptionAttribute
        /// elements assigned to each enum item
        /// </summary>
        /// <typeparam name="TEnum">The enum type that should be retrieved</typeparam>
        /// <param name="description">The description that should be searched</param>
        /// <param name="result">The matched enum item if it was found</param>
        /// <returns>Whether or not the enum item was found or not</returns>
        public static bool TryGetEnumByDescription<TEnum>(string description, out TEnum result)
            where TEnum : Enum
        {
            return TryGetEnumByDescription(description, false, out result);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Program.cs

using System;
using System.ComponentModel;

namespace ConvertStringToEnum
{
    enum Priority
    {
        [Description("Very important bru!")]
        High = 1,
        [Description("Look at it when you have a chance")]
        Medium = 2,
        [Description("Maybe take a look if you're bored")]
        Low = 3
    }

    class Program
    {
        static void Main(string[] args)
        {
            Priority result;
            EnumReflection.TryGetEnumByDescription("Very important bru!", out result);

            // Match using case-insensitive string comparison. We are also
            // using C# 7.0's parameter type inlining feature here.
            EnumReflection.TryGetEnumByDescription("Maybe take a look if you're BORED", true, out Priority result2);

            Console.WriteLine($"result: {result}");
            Console.WriteLine($"result2: {result2}");

            // Try find an enum that doesn't exist
            if (EnumReflection.TryGetEnumByDescription("Not sure what this is", out Priority result3))
                Console.WriteLine($"result3: {result3}");
            else
                Console.WriteLine("Could not find the specified enum item :(");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Advantages

  • Allows more flexibility in how an enum item should be picked based on a given string (you don't have to use the DescriptionAttribute only)
  • Can use case-insensitive comparison
  • Can return a typed enum using the generic type overload ( Enum.TryParse<TEnum>() )

Disadvantages

  • Requires writing additional methods

Closing

I hope you found this article helpful. If you have any other ideas as to how you can convert a string into an enum item please mention it in the comments below. Otherwise, if you have any questions you can also leave them below and I'll get back to you.

Sources

๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
ivankahl
Ivan Kahl

Posted on December 6, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About