1. 程式人生 > >對列舉值(Enum)進行位操作(AND & OR)

對列舉值(Enum)進行位操作(AND & OR)

這裡我們可以解釋為什麼第三個值ShowToolbox可以為4,5..而不能為3。

也就是說它的值不應該是前幾項值的複合值。【我的理解是 不能前幾位的和】

有一個比較簡單的方法就是用2的n次方來依次為每一項賦值,例如 1,2,4,8,16,32,64..... 

對列舉值(Enum)進行位操作(AND & OR)

這是我在部落格園的第一篇隨筆,其實也不能說是隨筆只能算是一篇翻譯稿,呵呵,這個就是以後我在部落格園的主要隨筆方式了。

對列舉值(Enum)進行位操作(AND & OR)

對列舉值進行AND 和 OR 操作是 .Net 中最不常用的功能之一,在讀了本文之後你將會發覺它其實也是一個比較有用的功能。

在做專案的時候我們可能經常會碰到這樣一種情況:我們需要儲存一些boolean值,然後在我們定義的類裡面對應的新增一個Isxxxx 屬性。比如說使用者許可權物件(IsAdmin,IsUser,IsPowerUser等)。建立和檢查這樣的一些相關屬性,然後還要注意這些屬性之間的組合,隨著這樣的屬性數量的增加,我們會發覺編寫和維護程式碼的工作量會相當的大而且容易出錯。

對於以上情況位操作(AND和OR)就可以相當輕鬆的進行處理,注意AND和OR是位操作符,他們是在數字的二進位制表示層上進行操作。

如果你對二進位制數不熟悉,請先參考相關資料。

二進位制數上的操作有很多種,我們這裡只需要用到AND和OR.

列舉型別(Enum)中的所有值都是整數,把一個整數用二進位制進行表示的時候,我們可以把每一位都當作是一個boolean值,這樣一個整數就可以來儲存一個boolean值的列表。

為了可以方便的實現這個功能,我們規定在列舉物件當中儲存的值只能夠是2的冪。

下面我們舉個例子,我們定義一個列舉物件來決定到底把什麼調料放在Pizza上面。

< Flags() > Public Enum Toppings ‘注意需要Flags標記 表明是位編碼

     None = 0      '務必定義一個等於0的列舉值

     Pepperoni = 1

     Mushrooms = 2

     Onions    = 4

     Anchovies = 8

     Peppers   = 16

     Pineapple = 32

End Enum

然後我們建立一個MakePizza的方法,它的輸入引數是 Toppings列舉值

MakePizza(UseToppings as Toppings)

在MakePizza方法內部我們首先定義一個列舉變數(MyToppings),對所有我們需要的值進行OR操作,然後賦值給它。

Dim MyToppings as Toppings 

 MyToppings = Mushrooms OR Onions OR Peppers

現在儲存在MyToppings中的值是22.

00000010 (Mushrooms - 2)

00000100 (Onions - 4)

00010000 (Peppers - 16)

--------―― OR

00010110 (22)

在MakePizza(UseToppings as Toppings)方法內部,我們需要判斷到底是什麼值產生了MyToppings(22)。

為了實現這個目的,我們把MyToppings與傳入的UseTopping進行AND操作。任何非零的操作結果代表一個True值。

現在我們來測試一下,如果傳入Pepperoni,

If UseToppings AND Toppings.Pepperoni Then

 '新增 pepperonis

End If

操作結果是 0(false)

00010110 (UseToppings - 22)

00000001 (Pepperoni - 1)

-------- AND

00000000 (0)

如果傳入Onions

結果是true(大於0)

00010110 (UseToppings - 22)

00000100 (Onions - 4)

-------- AND

00000100 (4)

通過這樣的方法,我們可以節省了儲存我們要表示的物件的儲存空間(在資料庫當中或者記憶體當中)

我們不用建立Pepperoni, Onions, Mushrooms等的true/false列,只要儲存一個數字22就可以了

通過這個例子,大家可以舉一反三,比如說應用在使用者許可權上面(Edit, ReadOnly, Admin等)

你可以建立一個使用者許可權的列舉,然後把他們儲存在資料庫的一列上就可以了。

我們還可以在sql語句內部充分利用這個方便性,比如說

SELECT * FROM AUTHORS

WHERE UserRight & P_UserRight > 0

我們把儲存在列UserRight的值和傳入引數值P_UserRight進行 & 操作,來判斷滿足許可權的列。

Note:對於Enum列舉型別我們可以利用它的ToString方法和Parse方法

dim top as Toppings = Toppings.Pepperoni OR Toppings.Onions OR Toppings.Pineapple

Dim strTop as string = top.ToString()

strTop中儲存的值就是 “Pepperonii,Onions,Pineapple”

列舉的ToString方法返回一個列表,列表中包含所有相對應的值,值與值之間以逗號分隔;

Parse方法

Dim top2 as Toppings = CType([Enum].Parse(GetType(Toppings), "Onions,Pineapple"),Toppings)

原文地址: http://www.johnsample.com/articles/BitwiseEnums.aspx

btw:我不知道這篇文章應該放在哪個區,請dudu指導一下。