Escribí un conjunto de métodos de extensión hace un tiempo que funcionan para varios tipos diferentes de Enums. Uno en particular funciona para lo que está tratando de lograr y maneja Enums con FlagsAttributeasí como Enums con diferentes tipos subyacentes.
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;
}
Desde allí, puede agregar otros métodos de extensión más específicos.
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);
}
Este cambiará los tipos de mensajes de correo Enumelectrónico como está intentando hacer.
public static tEnum ChangeType<tEnum>(this Enum e) where tEnum : IComparable
{
return SetFlags(e, default(tEnum), true, false);
}
Tenga en cuenta, sin embargo, que PUEDE convertir entre cualquiera Enumy cualquier otro Enumutilizando este método, incluso aquellos que no tienen banderas. Por ejemplo:
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>();
}
La variable turtletendrá un valor de Turtle.Blue.
Sin embargo, existe seguridad frente a Enumvalores indefinidos con este método. Por ejemplo:
static void Main(string[] args)
{
Turtle turtle = Turtle.Yellow;
WriteAccess access = turtle.ChangeType<WriteAccess>();
}
En este caso, accessse establecerá en WriteAccess.ReadWrite, ya que WriteAccess Enumtiene un valor máximo de 3.
Otro efecto secundario de mezclar Enums con FlagsAttributey sin él es que el proceso de conversión no dará como resultado una coincidencia de 1 a 1 entre sus valores.
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>();
}
En este caso, letterstendrá un valor de en Letters.Hlugar de Letters.D, ya que el valor de respaldo de Flavors.Peaches 8. Además, una conversión de Flavors.Cherry | Flavors.Grapea Lettersproduciría Letters.C, lo que puede parecer poco intuitivo.