Bir süre önce birkaç farklı tür için çalışan bir küme genişletme yöntemi yazdım Enum. Eğer başarmak için çalışıyoruz ve kolları ne için özellikle eserlerinde biri Enumolan lar FlagsAttributeyanı sıra Enumfarklı altta yatan türleriyle s.
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;
}
Oradan, diğer daha spesifik uzatma yöntemlerini ekleyebilirsiniz.
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);
}
Bu Enum, yapmaya çalıştığınız gibi türlerini değiştirecek .
public static tEnum ChangeType<tEnum>(this Enum e) where tEnum : IComparable
{
return SetFlags(e, default(tEnum), true, false);
}
Yine de, bayrakları olmayanlar da dahil olmak üzere, bu yöntemi kullanarak herhangi biri Enumve diğerleri arasında dönüşüm YAPABİLECEĞİNİZ konusunda uyarılmalıdır Enum. Örneğin:
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>();
}
Değişkenin turtledeğeri olacakTurtle.Blue .
Bununla birlikte, Enumbu yöntem kullanıldığında tanımlanmamış değerlerden güvenlik vardır . Örneğin:
static void Main(string[] args)
{
Turtle turtle = Turtle.Yellow;
WriteAccess access = turtle.ChangeType<WriteAccess>();
}
Bu durumda, accessayarlanacak WriteAccess.ReadWriteberi, WriteAccess Enum3 maksimum değere sahiptir.
EnumS ile FlagsAttributeve onsuz olanları karıştırmanın bir başka yan etkisi de , dönüştürme işleminin değerleri arasında 1'e 1 eşleşme ile sonuçlanmamasıdır.
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>();
}
Bu durumda, lettersbir değere sahip olacaktır Letters.Hyerine Letters.Darkalık değeri için, Flavors.Peachaynı zamanda 8 olan bir dönüşüm, Flavors.Cherry | Flavors.Grapeiçin Lettersdoğuracak Letters.C, unintuitive görünebilir olan.