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
I wrote a set extension methods a while back that work for several different kinds of Enum
s. One in particular works for what you are trying to accomplish and handles Enum
s with the FlagsAttribute
as well as Enum
s with different underlying types.
public static tEnum SetFlags(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(this Enum e, tEnum flags) where tEnum : IComparable
{
SetFlags(e, flags, true);
}
public static tEnum RemoveFlags(this Enum e, tEnum flags) where tEnum : IComparable
{
SetFlags(e, flags, false);
}
This one will change types of Enum
s like you are trying to do.
public static tEnum ChangeType(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();
}
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();
}
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 Enum
s 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();
}
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.