[c#] convert an enum to another type of enum

I have an enum of for example 'Gender' (Male =0 , Female =1) and I have another enum from a service which has its own Gender enum (Male =0 , Female =1, Unknown =2)

My question is how can I write something quick and nice to convert from their enum to mine?

This question is related to c# enums

The answer is


Here's an extension method version if anyone is interested

public static TEnum ConvertEnum<TEnum >(this Enum source)
    {
        return (TEnum)Enum.Parse(typeof(TEnum), source.ToString(), true);
    }

// Usage
NewEnumType newEnum = oldEnumVar.ConvertEnum<NewEnumType>();

Just cast one to int and then cast it to the other enum (considering that you want the mapping done based on value):

Gender2 gender2 = (Gender2)((int)gender1);

I know that's an old question and have a lot of answers, However I find that using a switch statement as in the accepted answer is somewhat cumbersome, so here are my 2 cents:

My personal favorite method is to use a dictionary, where the key is the source enum and the value is the target enum - so in the case presented on the question my code would look like this:

var genderTranslator = new Dictionary<TheirGender, MyGender>();
genderTranslator.Add(TheirGender.Male, MyGender.Male);
genderTranslator.Add(TheirGender.Female, MyGender.Female);
genderTranslator.Add(TheirGender.Unknown, MyGender.Unknown);

// translate their to mine    
var myValue = genderTranslator[TheirValue];

// translate mine to their
var TheirValue = genderTranslator .FirstOrDefault(x => x.Value == myValue).Key;;

Of course, this can be wrapped in a static class and be used as an extension methods:

public static class EnumTranslator
{

    private static Dictionary<TheirGender, MyGender> GenderTranslator = InitializeGenderTranslator();

    private static Dictionary<TheirGender, MyGender> InitializeGenderTranslator()
    {
        var translator = new Dictionary<TheirGender, MyGender>();
        translator.Add(TheirGender.Male, MyGender.Male);
        translator.Add(TheirGender.Female, MyGender.Female);
        translator.Add(TheirGender.Unknown, MyGender.Unknown);
        return translator;
    }

    public static MyGender Translate(this TheirGender theirValue)
    {
        return GenderTranslator[theirValue];
    }

    public static TheirGender Translate(this MyGender myValue)
    {
        return GenderTranslator.FirstOrDefault(x => x.Value == myValue).Key;
    }

}

I wrote a set extension methods a while back that work for several different kinds of Enums. One in particular works for what you are trying to accomplish and handles Enums with the FlagsAttribute as well as Enums with different underlying types.

public static tEnum SetFlags<tEnum>(this Enum e, tEnum flags, bool set, bool typeCheck = true) where tEnum : IComparable
{
    if (typeCheck)
    {
        if (e.GetType() != flags.GetType())
            throw new ArgumentException("Argument is not the same type as this instance.", "flags");
    }

    var flagsUnderlyingType = Enum.GetUnderlyingType(typeof(tEnum));

    var firstNum = Convert.ToUInt32(e);
    var secondNum = Convert.ToUInt32(flags);

    if (set)
        firstNum |= secondNum;

    else
        firstNum &= ~secondNum;

    var newValue = (tEnum)Convert.ChangeType(firstNum, flagsUnderlyingType);

    if (!typeCheck)
    {
        var values = Enum.GetValues(typeof(tEnum));
        var lastValue = (tEnum)values.GetValue(values.Length - 1);

        if (newValue.CompareTo(lastValue) > 0)
            return lastValue;
    }

    return newValue;
}

From there you can add other more specific extension methods.

public static tEnum AddFlags<tEnum>(this Enum e, tEnum flags) where tEnum : IComparable
{
    SetFlags(e, flags, true);
}

public static tEnum RemoveFlags<tEnum>(this Enum e, tEnum flags) where tEnum : IComparable
{
    SetFlags(e, flags, false);
}

This one will change types of Enums like you are trying to do.

public static tEnum ChangeType<tEnum>(this Enum e) where tEnum : IComparable
{
    return SetFlags(e, default(tEnum), true, false);
}

Be warned, though, that you CAN convert between any Enum and any other Enum using this method, even those that do not have flags. For example:

public enum Turtle
{
    None = 0,
    Pink,
    Green,
    Blue,
    Black,
    Yellow
}

[Flags]
public enum WriteAccess : short
{
   None = 0,
   Read = 1,
   Write = 2,
   ReadWrite = 3
}

static void Main(string[] args)
{
    WriteAccess access = WriteAccess.ReadWrite;
    Turtle turtle = access.ChangeType<Turtle>();
}

The variable turtle will have a value of Turtle.Blue.

However, there is safety from undefined Enum values using this method. For instance:

static void Main(string[] args)
{
    Turtle turtle = Turtle.Yellow;
    WriteAccess access = turtle.ChangeType<WriteAccess>();
}

In this case, access will be set to WriteAccess.ReadWrite, since the WriteAccess Enum has a maximum value of 3.

Another side effect of mixing Enums with the FlagsAttribute and those without it is that the conversion process will not result in a 1 to 1 match between their values.

public enum Letters
{
    None = 0,
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H
}

[Flags]
public enum Flavors
{
    None = 0,
    Cherry = 1,
    Grape = 2,
    Orange = 4,
    Peach = 8
}

static void Main(string[] args)
{
    Flavors flavors = Flavors.Peach;
    Letters letters = flavors.ChangeType<Letters>();
}

In this case, letters will have a value of Letters.H instead of Letters.D, since the backing value of Flavors.Peach is 8. Also, a conversion from Flavors.Cherry | Flavors.Grape to Letters would yield Letters.C, which can seem unintuitive.


To be thorough I normally create a pair of functions, one that takes Enum 1 and returns Enum 2 and another that takes Enum 2 and returns Enum 1. Each consists of a case statement mapping inputs to outputs and the default case throws an exception with a message complaining about an unexpected value.

In this particular case you could take advantage of the fact that the integer values of Male and Female are the same, but I'd avoid that as it's hackish and subject to breakage if either enum changes in the future.


You could write a simple generic extension method like this

public static T ConvertTo<T>(this object value)            
    where T : struct,IConvertible
{
    var sourceType = value.GetType();
    if (!sourceType.IsEnum)
        throw new ArgumentException("Source type is not enum");
    if (!typeof(T).IsEnum)
        throw new ArgumentException("Destination type is not enum");
    return (T)Enum.Parse(typeof(T), value.ToString());
}

Given Enum1 value = ..., then if you mean by name:

Enum2 value2 = (Enum2) Enum.Parse(typeof(Enum2), value.ToString());

If you mean by numeric value, you can usually just cast:

Enum2 value2 = (Enum2)value;

(with the cast, you might want to use Enum.IsDefined to check for valid values, though)


I wrote this answer because I believe there are fundamental issues with the majority of answers already provided, and the ones that are acceptable are incomplete.

Mapping by enum integer value

This approach is bad simply because it assumes that the integer values of both MyGender and TheirGender will always remain comparable. In practice, it is very rare that you can guarantee this even within a single project, let alone a separate service.

The approach we take should be something that can be used for other enum-mapping cases. We should never assume that one enum identically relates to another - especially when we may not have control over one or another.

Mapping by enum string value

This is a little better, as MyGender.Male will still convert to TheirGender.Male even if the integer representation is changed, but still not ideal.

I would discourage this approach as it assumes the name values will not change, and will always remain identical. Considering future enhancements, you cannot guarantee that this will be the case; consider if MyGender.NotKnown was added. It is likely that you would want this to map to TheirGender.Unknown, but this would not be supported.

Also, it is generally bad to assume that one enum equates to another by name, as this might not be the case in some contexts. As mentioned earlier, an ideal approach would work for other enum-mapping requirements.

Explicitly mapping enums

This approach explictly maps MyGender to TheirGender using a switch statement.

This is better as:

  • Covers the case where the underlying integer value changes.
  • Covers the case where the enum names changes (i.e. no assumptions - the developer will need to update the code to handle the scenario - good).
  • Handles cases where enum values cannot be mapped.
  • Handles cases where new enum values are added and cannot be mapped by default (again, no assumptions made - good).
  • Can easily be updated to support new enum values for either MyGender or TheirGender.
  • The same approach can be taken for all enum mapping requirements.

Assuming we have the following enums:

public enum MyGender
{
    Male = 0,
    Female = 1,
}

public enum TheirGender
{
    Male = 0,
    Female = 1,
    Unknown = 2,
}

We can create the following function to "convert from their enum to mine":

public MyGender GetMyGender(TheirGender theirGender)
{
    switch (theirGender)
    {
        case TheirGender.Male:
            return MyGender.Male;

        case TheirGender.Female:
            return MyGender.Female;

        default:
            throw new InvalidEnumArgumentException(nameof(theirGender), (int)theirGender, typeof(TheirGender));
    }
}

A previous answer suggested returning a nullable enum (TheirGender?) and returning null for any unmatched input. This is bad; null is not the same as an unknown mapping. If the input cannot be mapped, an exception should be thrown, else the method should be named more explictly to the behaviour:

public TheirGender? GetTheirGenderOrDefault(MyGender myGender)
{
    switch (myGender)
    {
        case MyGender.Male:
            return TheirGender.Male;
            
        case MyGender.Female:
            return TheirGender.Female;
            
        default:
            return default(TheirGender?);
    }
}

Additional considerations

If it is likely that this method will be required more than once in various parts of the solution, you could consider creating an extension method for this:

public static class TheirGenderExtensions
{
    public static MyGender GetMyGender(this TheirGender theirGender)
    {
        switch (theirGender)
        {
            case TheirGender.Male:
                return MyGender.Male;

            case TheirGender.Female:
                return MyGender.Female;

            default:
                throw new InvalidEnumArgumentException(nameof(theirGender), (int)theirGender, typeof(TheirGender));
        }
    }
}

If you are using C#8, you can use the syntax for switch expressions and expression bodies to neaten up the code:

public static class TheirGenderExtensions
{
    public static MyGender GetMyGender(this TheirGender theirGender)
        => theirGender switch
        {
            TheirGender.Male => MyGender.Male,
            TheirGender.Female => MyGender.Female,
            _ => throw new InvalidEnumArgumentException(nameof(theirGender), (int)theirGender, typeof(TheirGender))
        };
}

If you will only ever be mapping the enums within a single class, then an extension method may be overkill. In this case, the method can be declared within the class itself.

Furthermore, if the mapping will only ever take place within a single method, then you can declare this as a local function:

public static void Main()
{
    Console.WriteLine(GetMyGender(TheirGender.Male));
    Console.WriteLine(GetMyGender(TheirGender.Female));
    Console.WriteLine(GetMyGender(TheirGender.Unknown));
    
    static MyGender GetMyGender(TheirGender theirGender)
        => theirGender switch
        {
            TheirGender.Male => MyGender.Male,
            TheirGender.Female => MyGender.Female,
            _ => throw new InvalidEnumArgumentException(nameof(theirGender), (int)theirGender, typeof(TheirGender))
        };
}

Here's a dotnet fiddle link with the above example.

tl;dr:

Do not:

  • Map enums by integer value
  • Map enums by name

Do:

  • Map enums explicitly using a switch statement
  • Throw an exception when a value cannot be mapped rather than returning null
  • Consider using extension methods

Based on Justin's answer above I came up with this:

    /// <summary>
    /// Converts Enum Value to different Enum Value (by Value Name) See https://stackoverflow.com/a/31993512/6500501.
    /// </summary>
    /// <typeparam name="TEnum">The type of the enum to convert to.</typeparam>
    /// <param name="source">The source enum to convert from.</param>
    /// <returns></returns>
    /// <exception cref="InvalidOperationException"></exception>
    public static TEnum ConvertTo<TEnum>(this Enum source)
    {
        try
        {
            return (TEnum) Enum.Parse(typeof(TEnum), source.ToString(), ignoreCase: true);
        }
        catch (ArgumentException aex)
        {
            throw new InvalidOperationException
            (
                $"Could not convert {source.GetType().ToString()} [{source.ToString()}] to {typeof(TEnum).ToString()}", aex
            );
        }
    }

If we have:

enum Gender
{
    M = 0,
    F = 1,
    U = 2
}

and

enum Gender2
{
    Male = 0,
    Female = 1,
    Unknown = 2
}

We can safely do

var gender = Gender.M;
var gender2   = (Gender2)(int)gender;

Or even

var enumOfGender2Type = (Gender2)0;

If you want to cover the case where an enum on the right side of the '=' sign has more values than the enum on the left side - you will have to write your own method/dictionary to cover that as others suggested.


You can use ToString() to convert the first enum to its name, and then Enum.Parse() to convert the string back to the other Enum. This will throw an exception if the value is not supported by the destination enum (i.e. for an "Unknown" value)


In case when the enum members have different values, you can apply something like this:

public static MyGender? MapToMyGender(this Gender gender)
{
    return gender switch
    {
        Gender.Male => MyGender.Male,
        Gender.Female => MyGender.Female,
        Gender.Unknown => null,
        _ => throw new InvalidEnumArgumentException($"Invalid gender: {gender}")
    };
}

Then you can call: var myGender = gender.MapToMyGender();

Update: This previous code works only with C# 8. For older versions of C#, you can use the switch statement instead of the switch expression:

public static MyGender? MapToMyGender(this Gender gender)
{
    switch (gender)
    {
        case Gender.Male: 
            return MyGender.Male;
        case Gender.Female:
            return MyGender.Female;
        case Gender.Unknown:
            return null;
        default:
            throw new InvalidEnumArgumentException($"Invalid gender: {gender}")
    };
}

public static TEnum ConvertByName<TEnum>(this Enum source, bool ignoreCase = false) where TEnum : struct
{
    // if limited by lack of generic enum constraint
    if (!typeof(TEnum).IsEnum)
    {
        throw new InvalidOperationException("enumeration type required.");
    }

    TEnum result;
    if (!Enum.TryParse(source.ToString(), ignoreCase, out result))
    {
        throw new Exception("conversion failure.");
    }

    return result;
}

you could write a simple function like the following:

public static MyGender ConvertTo(TheirGender theirGender)
{
    switch(theirGender)
    {
        case TheirGender.Male:
            break;//return male
        case TheirGender.Female:
            break;//return female
        case TheirGender.Unknown:
            break;//return whatever
    }
}