寫在前面
枚舉Enum 全稱(Enumeration),即一種由一組稱爲枚舉數列表的命名常量組成的獨特類型。能夠看出枚舉的出現時爲了使咱們能夠在程序中方便的使用一些特定值的常量,通常的使用你們都比較熟悉,本文主要介紹枚舉的特性 FlagAttribute。測試
FlagAttribute是什麼?
Flag 特性微軟的解釋是:指示能夠將枚舉做爲位域(即一組標誌)處理,FlagsAttribute屬性就是枚舉類型的一項可選屬性,它的主要做用是能夠將枚舉做爲位域處理(P.S. C#不支持位域)。所謂位域是單個存儲單元內相鄰二進制位的集合。經過爲枚舉添加這個屬性,能夠改變枚舉的一些行爲來知足咱們的須要。編碼
好比咱們有以下枚舉的定義:url
public enum OrderTypeEnum { Init, Complete, Waiting, Paid }
邏輯或操做我相信你們都比較熟悉了,對於整數來講,| 操做就是將其轉化爲二進制再進行或運算。OrderTypeEnum.Init | OrderTypeEnum.Complete作的工做其實是 0001 | 0010 = 0011 = 3再轉換成(OrderTypeEnum)3就是OrderTypeEnum.Paid了.spa
若是咱們對兩個枚舉值作 | 操做,那結果會是什麼樣呢?.net
OrderTypeEnum result = OrderTypeEnum.Waiting | OrderTypeEnum.Paid;
按照或操做的原理:0010 | 0011 = 0011(3) Paid ,實質上咱們想要的結果是想講兩個枚舉值都做爲或操做的結果,可是由於枚舉值默認是從0開始順次遞增的,那麼通過或操做以後就得不到咱們想要的結果,那怎麼辦呢,這時候就須要 給枚舉加上 [Flags] 的Attribute,咱們先來看一下FlagsAttribute定義的準則:code
- 使用FlagsAttribute枚舉纔是對數字值執行按位運算 (AND、 OR 獨佔或) 的自定義屬性。
- 在 2 的冪,即 一、 二、 四、 8 等中定義枚舉常量。 這意味着不重疊中組合的枚舉常量的各個標誌。
- 請考慮建立針對經常使用的標誌組合的枚舉的常數。 例如,若是你有用於文件 I/O 操做的枚舉包含枚舉的常數Read = 1和Write = 2,請考慮建立枚舉的常數ReadWrite = Read OR Write,它結合Read和Write標誌。 此外,可用於組合標誌的按位 OR 操做視爲在某些狀況下,不該爲用於簡單任務所需的一個高級的概念。
- 若是爲標誌枚舉常量中定義爲負數,由於不少標誌位置可能會設置爲 1,這可能會使你的代碼的混亂,並鼓勵編碼錯誤,請務必當心。
- 測試是否在數值中設置一個標誌一種簡便方式是執行按位,操做之間的數字值和標誌枚舉的常數,它將全部位都設置爲不對應於標誌的零的數字值中,而後測試該操做的結果是否等於該標誌枚舉常量。
- 使用None用做枚舉其值爲零的常量的標誌名稱。 不能使用None按位運算中,來測試一個標誌,由於結果始終爲零的枚舉的常數。 可是,你能夠執行的邏輯不之間的數字值的按位、 比較和None枚舉的常量,以肯定是否已設置在數值中的任何位。
- 若是你建立而不是標誌枚舉的值枚舉,它是仍必要建立None枚舉的常數。 緣由是,默認狀況下用於枚舉的內存初始化爲零的公共語言運行時。 所以,若是未定義其值爲零的常量,枚舉將包含在建立時非法值。
- 若是你的應用程序須要表示明顯默認狀況下,請考慮使用其值爲零表示默認值的枚舉的常數。 若是沒有任何默認狀況下,請考慮使用其值爲零的枚舉的常數意味着不禁任何其餘枚舉常量表示這種狀況。
- 未定義一個枚舉值,只是爲了鏡像與枚舉自己的狀態。 例如,不定義僅用於枚舉的結束標記的枚舉的常數。 若是你須要肯定在枚舉的最後一個值,請顯式檢查該值。 此外,你能夠執行範圍檢查第一個和最後一個枚舉常量,若是範圍內的全部值都是有效。
- 不要指定保留供未來使用的枚舉的常數。
- 當你定義的方法或屬性,它採用做爲值的枚舉的常數時,請考慮驗證值。 緣由是,即便該數值不在枚舉中定義,你能夠強制轉換爲枚舉類型的數字值。
咱們看到第二句告訴咱們當加了Flags的特性以後默認的枚舉值就會以2的冪一次遞增,好比 20,21,22,23(1,2,4,8....)blog
那咱們從新看一下從新定義以後的或操做會是什麼結果呢?內存
[Flags] public enum OrderTypeEnum { Init, Complete, Waiting, Paid }
此時咱們再來看:OrderTypeEnum result = OrderTypeEnum.Complete | OrderTypeEnum.Waiting | OrderTypeEnum.Paid ;get
0010 | 0100 | 1000 = 1110 咱們能夠看到實質上就是作了二進制的或運算,將全部位值作了合併it
當咱們能夠用作位運算的時候,就不只僅是或,與,非,異或等操做均可以實現。
咱們知道經過這樣能夠把枚舉值合併 OrderTypeEnum result = OrderTypeEnum.Complete | OrderTypeEnum.Waiting | OrderTypeEnum.Paid ;
那麼同理也能夠來判斷這樣的集合中是否包含某個枚舉值:
result.HasFlag(OrderTypeEnum.Paid)
寫在最後
枚舉經過添加Flags的特性使得它可以擁有位運算的能力,更方便了咱們再平常代碼中的使用。
參考資料:http://www.alanzucconi.com/2015/07/26/enum-flags-and-bitwise-operators/