Converting Enum Types By Value in C#
Wed, 30 Jun 2021 23:00 UTC 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);
});
}
}
-
Web Analytics
-
.NET
-
API Versioning and Basic UI Authentication with OpenAPI (Swagger / Swashbuckle) in .NET Core 6
-
Converting Enum Types By Value in C#
-
Implementing Microsoft.Extensions.Logging.ILogger with NLog
-
ASP.NET File Uploader with SignalR Progress Bar and Extended Input Stream Processing
-
How to inject Google Adsense In-Article script into your HTML (ASP.NET Core Razor)
-
Robust Error Handling in ASP.NET Core
-
A Utility Class for Finding Database Deadlocks in .NET Applications
-
Sanitizing HTML in .NET Core
-
Uploading Directly to S3 from Client Using Pre-Signed URLs (JavaScript, .NET)
-
Including Automated Swagger Documentation for API Dependencies
-
API Versioning and Basic UI Authentication with OpenAPI (Swagger / Swashbuckle) in .NET Core 6
-
Principles
-
JavaScript & TypeScript
-
AI
-
Software Architecture
-
General
-
Docker