之一:簡要介紹C#位域(flags)的相關知識
作者:shelley 2018-08-12 來源:51CTO
C#位域主要用於.net裏面對於某一個事物有多種混合狀態時使用,單一的枚舉更的在事物只具有單一屬性時使用。爲了更好的實現混合狀態,我們可以在枚舉加上C#位域標籤。下面的這個就是我們在本文中用到的實例:
[Flags]
public enum Week
{
[Description("星期一")]
Monday = 1 < < 0,
[Description("星期二")]
Tuesday = 1 < < 1,
[Description("星期三")]
Wednesday = 1 < < 2,
[Description("星期四")]
Tursday = 1 < < 3,
[Description("星期五")]
Friday = 1 < < 4,
[Description("星期六")]
Saturday = 1 < < 5,
[Description("星期日")]
Sunday = 1 < < 6
}
位域支持的運算符
- “|”:表示兩邊求並集(元素相加,相同元素只出現一次)
Week week = Week.Tuesday | Week.Monday | Week.Monday;
MessageBox.Show(Convert.ToString(week));
這段代碼的結果就是 Monday,Tuesday
- “&”:表示兩邊是否其中一個是另外一個的子集,如果是返回子集,否則返回0(如果其中一個包含另外一個,返回被包含的,否則返回0)
week = Week.Monday & week;
MessageBox.Show(week.ToString());與week = week & Week.Monday;
MessageBox.Show(week.ToString());
上面這兩段代碼的結果是相同的,如果week的初始值爲:Monday,Tuesday,返回的結果爲:Monday
3.“^”:表示從兩者的並集中去除兩者的交集(把兩個的元素合併到一起,如果兩個中有公共元素,要將這個公共元素從合併的結果中去除)
week = (Week.Monday | Week.Wednesday)^ (Week.Tuesday | Week.Monday);
MessageBox.Show(week.ToString());
week = (Week.Monday | Week.Wednesday) ^ (Week.Tuesday | Week.Sunday);
MessageBox.Show(week.ToString());
上面兩個返回的結果應該爲:Tuesday,Wednesday 和 Monday,Tuesday,Wednesday,Sunday
4.“~”:表示取反,返回的結果我還不知道應該是什麼,以後再查一下。用法主要和“&”一起使用,例如:去除其中的某個元素
week = Week.Tuesday | Week.Monday | Week.Wednesday;
week = week &(~Week.Monday);
MessageBox.Show(week.ToString());
上面返回的結果爲:Tuesday,Wednesday
正逆轉化
上面的內容存在數據庫時我們可能爲了簡單隻存取數字即可,例如:1表示Monday,3表示Monday,Tuesday。我們可以根據數據庫裏面的值方便獲取存儲的內容,代碼如下:
week = Week.Monday | Week.Tuesday;
MessageBox.Show(Convert.ToString((int)week));
week = (Week)Enum.Parse(typeof(Week), "10");
MessageBox.Show(week.ToString());
返回的結果爲:3 和 Tuesday,Tursday
獲取Description標籤內容
我們既然可以給裏面的值加上Description,就可以在程序中獲取到這個內容,至於用途,大家自己看吧,東西擺出來,大家自己隨便怎麼用,下面的代碼是從網上找到的,內容如下:
/// < summary>
/// 從枚舉類型和它的特性讀出並返回一個鍵值對
/// < /summary>
/// < param name="enumType">Type,該參數的格式爲typeof(需要讀的枚舉類型)< /param>
/// < returns>鍵值對< /returns>
public static NameValueCollection GetNVCFromEnumValue(Type enumType)
{
NameValueCollection nvc = new NameValueCollection();
Type typeDescription = typeof(DescriptionAttribute);
System.Reflection.FieldInfo[] fields = enumType.GetFields();
string strText = string.Empty;
string strValue = string.Empty;
foreach (FieldInfo field in fields)
{
if (field.FieldType.IsEnum)
{
strValue = ((int)enumType.InvokeMember(field.Name, BindingFlags.GetField, null, null, null)).ToString();
object[] arr = field.GetCustomAttributes(typeDescription, true);
if (arr.Length > 0)
{
DescriptionAttribute aa = (DescriptionAttribute)arr[0];
strText = aa.Description;
}
else
{
strText = field.Name;
}
nvc.Add(strText, strValue);
}
}
return nvc;
}
C#位域(flags)的相關知識就介紹到這裏。
本文原作者shelley,原文鏈接http://developer.51cto.com/art/200909/148735.htm
之二:C# 特性(Attribute)之Flag特性
本文參考自C# 位域[flags],純屬讀書筆記,加深記憶
[Flags]的微軟解釋是“指示可以將枚舉作爲位域(即一組標誌)處理。”其實就是在編寫枚舉類型時,上面附上Flags特性後,用該枚舉變量是既可以象整數一樣進行按位的“|”或者按位的“&”操作了。
另外一個是在引用COM組件時使用,我沒有用過,你可以查看MSDN
這種用處很大,比如權限、執行狀態等,都可以用一個int型保存到數據庫中,C#中使用枚舉可以處理這個問題。
.Net中的枚舉一般有兩種用法
(1)、表示唯一的元素序列,列入一週天裏面的各天
(2)、表示多種的複合狀態,這個時候一般需要爲枚舉加上[Flags]特性爲標記
下面通過代碼演示[Flags]特性的作用
1、不加[Flag]特性的代碼
複製代碼
public enum Permission
{
create = 1,
read = 2,
update = 4,
delete = 8,
}
static void Main(string[] args)
{
Permission permission = Permission.create | Permission.read | Permission.update | Permission.delete;
Console.WriteLine("1、枚舉創建,並賦值……");
Console.WriteLine(permission.ToString());
Console.WriteLine((int)permission);
}
複製代碼
輸出:
2、加[Flag]特性的代碼
複製代碼
**[Flags]
public enum Permission
{
create = 1,
read = 2,
update = 4,
delete = 8,
}**
static void Main(string[] args)
{
Permission permission = Permission.create | Permission.read | Permission.update | Permission.delete;
Console.WriteLine("1、枚舉創建,並賦值……");
Console.WriteLine(permission.ToString());
Console.WriteLine((int)permission);
}
複製代碼
輸出:
3、分析上面的代碼,發現加上[Flags]特性之後,對於枚舉的追加操作,沒加特性的只是單純的從值上的相加,而加了特性的則是枚舉上的相加。這也導致了create=1,read=2,update=4,delete=8的原因,因爲兩個狀態的值相加不能等於其中任何一個的值,如果相等的話,那麼[Flag]也就失去了使用它的意義(因爲給一個用戶賦予進行read和delete操作的權限,如果兩個相加的值等於update,那不亂套了麼,所以這裏兩個狀態的值相加不能等於其中任何一個的值)。當然這裏如果加一個可讀可刪的權限,那麼就可以這樣寫了:readAndDelete=10。是不是很靈活!!!
這種用處很大,比如權限、執行狀態等,都可以用一個int型保存到數據庫中,C#中使用枚舉可以處理這個問題。
================================
以上都有不足,這裏增加了一些,聲明的方式:
1)從零開始。 零會屏蔽以上所有的項目,怎麼運算都是0。
[Flags]
internal enum HttpHeaderType
{
** Unspecified = 0,
Request = 1,**
Response = 1 << 1,
Restricted = 1 << 2,
MultiValue = 1 << 3,
MultiValueInRequest = 1 << 4,
MultiValueInResponse = 1 << 5
}
//如何處理判斷邏輯。
if ( value ) {
flags |= (int)GeneralBitFlags.UnicodeText;//增加
}
else {
flags &= ~(int)GeneralBitFlags.UnicodeText;//減少
}
判斷====>>>
**Short localFlags=1;
if ( (localFlags **& ( int )(GeneralBitFlags.Patched | GeneralBitFlags.StrongEncryption | GeneralBitFlags.EnhancedCompress | GeneralBitFlags.HeaderMasked)) != 0 ) {
![screenshot]
(
h public enum InstalledHook
{
/// <summary>
/// 沒有安裝鉤子
/// </summary>
None = 0,
/// <summary>
/// 安裝了WH_GETMESSAGE 鉤子
/// </summary>
GetMessage = 1,
/// <summary>
/// 安裝了WH_CALLWNDPROC鉤子
/// </summary>
CallWndProc = GetMessage << 1,
/// <summary>
/// 安裝了WH_MSGFILTER鉤子
/// </summary>
SystemMessage = CallWndProc << 1,
All = GetMessage | CallWndProc | SystemMessage,
}
//16進制的聲明
public enum SPIActions
{
SPI_GETBEEP = 0x0001,
SPI_SETBEEP = 0x0002,
SPI_GETMOUSE = 0x0003,
SPI_SETMOUSE = 0x0004,
SPI_GETBORDER = 0x0005,
SPI_SETBORDER = 0x0006,
SPI_GETKEYBOARDSPEED = 0x000A,
SPI_SETKEYBOARDSPEED = 0x000B,
SPI_LANGDRIVER = 0x000C,
SPI_ICONHORIZONTALSPACING = 0x000D,
SPI_GETSCREENSAVETIMEOUT = 0x000E,
SPI_SETSCREENSAVETIMEOUT = 0x000F,
SPI_GETSCREENSAVEACTIVE = 0x0010,
SPI_SETSCREENSAVEACTIVE = 0x0011,
SPI_GETGRIDGRANULARITY = 0x0012,
}