Saya menulis metode ekstensi set beberapa waktu lalu yang berfungsi untuk beberapa jenis yang berbeda Enum. Satu secara khusus bekerja untuk apa yang Anda coba capai dan tangani Enumdengan FlagsAttributeserta Enumdengan jenis dasar yang berbeda.
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;
}
Dari sana Anda dapat menambahkan metode ekstensi lain yang lebih spesifik.
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);
}
Yang ini akan mengubah jenis Enumseperti yang Anda coba lakukan.
public static tEnum ChangeType<tEnum>(this Enum e) where tEnum : IComparable
{
return SetFlags(e, default(tEnum), true, false);
}
Berhati-hatilah, meskipun, Anda BISA mengonversi antara salah satu Enumdan yang lain Enummenggunakan metode ini, bahkan yang tidak memiliki bendera. Sebagai contoh:
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>();
}
Variabel turtleakan memiliki nilai Turtle.Blue.
Namun, ada keamanan dari Enumnilai yang tidak ditentukan dengan menggunakan metode ini. Misalnya:
static void Main(string[] args)
{
Turtle turtle = Turtle.Yellow;
WriteAccess access = turtle.ChangeType<WriteAccess>();
}
Dalam kasus ini, accessakan disetel ke WriteAccess.ReadWrite, karena WriteAccess Enummemiliki nilai maksimum 3.
Efek samping lain dari pencampuran Enums dengan FlagsAttributedan yang tanpanya adalah bahwa proses konversi tidak akan menghasilkan kecocokan 1 banding 1 di antara nilainya.
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>();
}
Dalam kasus ini, lettersakan memiliki nilai Letters.Halih - alih Letters.D, karena nilai dukungan Flavors.Peachadalah 8. Selain itu, konversi dari Flavors.Cherry | Flavors.Grapemenjadi Lettersakan menghasilkan Letters.C, yang tampaknya tidak intuitif.