.NET Framework除了一般開發者很常使用的列舉型別外(Enumeration), 原來也有支援複合列舉的使用,在MSDN中文翻譯為旗標(Flag), 其實早在.NET 1.1就開始支援了(汗,過去專案中還真的沒有使用過), 這種標示為旗標的列舉,最大的差別就是該型別被認定會直接拿來進行位元運算。
.NET Framework除了一般開發者很常使用的列舉型別外(Enumeration), 原來也有支援複合列舉的使用,在MSDN中文翻譯為旗標(Flag), 其實早在.NET 1.1就開始支援了(汗,過去專案中還真的沒有使用過), 這種標示為旗標的列舉,最大的差別就是該型別被認定會直接拿來進行位元運算。
[SerializableAttribute]
[AttributeUsageAttribute(AttributeTargets.Enum, Inherited = false)]
[ComVisibleAttribute(true)]
public class FlagsAttribute : Attribute
這個Flag Attribute直接繼承了Attribute類別, 並且只能標示於Enum的型別上,而且無法繼承,一旦Enum被標示了此Attribute,則被視為該型別物件會直接做位元運算,所以在MSDN的GuideLine上, 也表明此種列舉方式正常以2的次方來設定其值:
“以乘冪數 2 來定義列舉常數,也就是 1、2、4、8 等。
一般最常作的應用應該就算權限了, 我們可以針對每一個二次方數字設定其對應擁有權限如下:
[Flags]
public enum enumPermission
{
Guest = 1,
Member = 2,
Leader = 4,
Manager = 8,
}
然後列出這個列舉的所有組合
//All Combination of flag enumation
for (int val = 0; val <= 16; val++)
Console.WriteLine("{0,3} - {1:G}", val, (enumPermission)val);
並試著以迴圈執行此Flag Enum所有的可能情境, 如下圖所列,如此在權限欄位設定中,預設會有0~15種組合。
而在權限的判斷上,當然也就要用位元運算的OR / AND。如果今天我們想判斷所有具有Member權限的組合, 藉由(val & enumPermission.Member) == enumPermission.Member 即可判斷出
//All Combination of Member permission flag enumation
for (int val = 0; val <= 16; val++)
{
if ((val & (int)enumPermission.Member) == (int)enumPermission.Member)
Console.WriteLine("{0,3} - {1:G}", val, (enumPermission)val);
}
如此我們便可以捉出所有具有Member權限的組合。
由在權限設定上, 則是用OR的方式來達到
enumPermission p = (0 | enumPermission.Member);
p = (p | enumPermission.Manager);
Console.WriteLine(p);
如此可以設定一個p變數具有Member及Manager的權限,而利用列舉的好處讓可讀性很高。
從.NET 1.1就有的東西居然過了十多年才發現,藉由撰寫這篇把玩了一下,也讓自已不會忘記。
參考
https://msdn.microsoft.com/zh-tw/library/System.FlagsAttribute(v=vs.110).aspx