For software development and maintenance, contact me at contact@appsoftware.com or via appsoftware.com


Converting Enum Types By Value in C#

Wed, 30 Jun 2021 by garethbrown

If you find yourself having to convert between values in two identical Enums and there is no way that your code base allows you to reconcile those enums into the same type, or if you have enums with only letter case differences, this is a means of a conversion from source to target using generics.

public static class EnumExtensions
{
    public static TTargetEnumType ConvertByName<TTargetEnumType>(this Enum source, bool verifyAllEnumMembersMatch = false, bool ignoreCase = false) where TTargetEnumType : struct, Enum
    {
        if (verifyAllEnumMembersMatch)
        {
            foreach (var sourceEnumValue in Enum.GetValues(source.GetType()))
            {
                bool parsed = Enum.TryParse<TTargetEnumType>(sourceEnumValue.ToString(), ignoreCase, out _);

                if (!parsed)
                {
                    throw new InvalidOperationException($"Cannot convert to {typeof(TTargetEnumType).Name} from {source.GetType().Name}, failure on source value {sourceEnumValue}");
                }
            }

            foreach (var targetEnumValue in Enum.GetValues(typeof(TTargetEnumType)))
            {
                bool parsed = Enum.TryParse(source.GetType(), targetEnumValue.ToString(), ignoreCase, out _);

                if (!parsed)
                {
                    throw new InvalidOperationException($"Cannot convert to {source.GetType().Name} from {typeof(TTargetEnumType).Name}, failure on target value {targetEnumValue}");
                }
            }
        }

        string sourceString = source.ToString();

        return Enum.Parse<TTargetEnumType>(sourceString, ignoreCase);
    }
}

Some basic tests for this class are as follows

public class EnumExtensionTests
{
   private enum TestEnum1
   {
       A,
       B,
       C
   }

   private enum TestEnum2
   {
       A,
       B,
       C
   }

   private enum TestEnum3
   {
       A
   }

   [Fact]
   public void TestBasicConversion()
   {
       var testEnum2AAs1A = TestEnum1.A.ConvertByName<TestEnum2>();

       Assert.Equal(TestEnum2.A, testEnum2AAs1A);

       var testEnum2BAs1B = TestEnum1.B.ConvertByName<TestEnum2>();

       Assert.Equal(TestEnum2.B, testEnum2BAs1B);

       var testEnum2CAs1C = TestEnum1.C.ConvertByName<TestEnum2>();

       Assert.Equal(TestEnum2.C, testEnum2CAs1C);
   }

   [Fact]
   public void TestThrowsOnMismatchedEnumsAndVerifyAllEnumMembersMatch()
   {
       Assert.Throws<InvalidOperationException>(() =>
       {
           TestEnum3.A.ConvertByName<TestEnum2>(ignoreCase: false, verifyAllEnumMembersMatch: true);
       });

       Assert.Throws<InvalidOperationException>(() =>
       {
           TestEnum2.A.ConvertByName<TestEnum3>(ignoreCase: false, verifyAllEnumMembersMatch: true);
       });
   }

   [Fact]
   public void TestDoesNotThrowOnMismatchedEnumsAndVerifyAllEnumMembersMatchIsFalse()
   {
       TestEnum3.A.ConvertByName<TestEnum2>(ignoreCase: false, verifyAllEnumMembersMatch: false);

       TestEnum2.A.ConvertByName<TestEnum3>(ignoreCase: false, verifyAllEnumMembersMatch: false);
   }

   [Fact]
   public void TestThrowsOnMismatchedEnumsAndVerifyAllEnumMembersMatchFalse()
   {
       Assert.Throws<ArgumentException>(() =>
       {
           TestEnum1.C.ConvertByName<TestEnum3>(ignoreCase: false, verifyAllEnumMembersMatch: false);
       });
   }
}

The information provided on this Website is for general informational and educational purposes only. While we strive to provide accurate and up-to-date information, we make no warranties or representations, express or implied, as to the accuracy, completeness, reliability, or suitability of the content, including code samples and product recommendations, presented on this Website.

The use of any information, code samples, or product recommendations on this Website is entirely at your own risk, and we shall not be held liable for any loss or damage, direct or indirect, arising from or in connection with the use of this Website or the information provided herein.
UI block loader
One moment please ...