簡要介紹C#位域(flags)的相關知識+各種整理!

之一:簡要介紹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
}
位域支持的運算符

  1. “|”:表示兩邊求並集(元素相加,相同元素只出現一次)

Week week = Week.Tuesday | Week.Monday | Week.Monday;
MessageBox.Show(Convert.ToString(week));
這段代碼的結果就是 Monday,Tuesday

  1. “&”:表示兩邊是否其中一個是另外一個的子集,如果是返回子集,否則返回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,

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章