列舉型別與位運算

K戰神發表於2015-04-20

目錄

  • 列舉
  • 位運算

一、列舉

列舉型別是名稱與值的組合。

列舉型別是值型別。

1、為什麼列舉型別是名稱與值得組合?有時我只看到鍵名稱,沒有看到相對的值。

public enum Options
{
            Insert,
            Update,
            Save,
            Delete,
            Query
}

編譯器會給上面補充完整

public enum Options
{
            Insert=0,
            Update=1,
            Save=2,
            Delete=3,
            Query=4
}

預設從0開始,依次賦值。

2、為什麼列舉型別是值型別

因為System.Enum派生於System.ValueType,而System.ValueType直接派生自System.Object

編譯器遇到列舉型別時,會有自己的理解:

internal struct Options:System.Enum
 {
            public const Options Insert = (Options)0;
            public const Options Update = (Options)1;
            public const Options Save = (Options)2;
            public const Options Delete = (Options)3;
            public const Options Query = (Options)4;
            public int value__;
}

雖然Enum型別不能繼承,但是可以看出編譯器對待列舉型別所形成自己的理解,讓我們明白其原理。

3、操作列舉型別

(1) GetUnderLyingType:返回容納一個列舉型別的值的基礎型別

每個列舉型別都有一個基礎型別,預設是int.所以上面編譯器預設為我們填充int型別的值0~4。

當然這個基礎型別也可以自己指定,可以為byte\sbyte\short\usshot\int\uintr\long\ulong

public enum Options:byte
{
            Insert,
            Update,
            Save,
            Delete,
            Query
}
var type= Enum.GetUnderlyingType(typeof(Options));

 string strs = type.ToString();

列舉型別是基元型別,我們可以對其例項進行許多平時的操作符操作,而每個列舉例項,對應著value__欄位。

 

(2)GetValues:獲取一個陣列,該陣列的每個元素都包含鈣元素的名稱和對應的值。

System.Collections.Generic.Dictionary<int,string> opsDic=new     System.Collections.Generic.Dictionary<int,string>();
Options[] ops = (Options[])Enum.GetValues(typeof(Options));
foreach (var o in ops)
{
                try
                {
                    opsDic.Add((int)o, o.ToString());
                }
                catch (Exception ex)
                {
                    Console.WriteLine("鍵值{0}已存在", (int)o);
                }
}    


(3)GetNames:返回一組字串名稱陣列。

string[] opsNames = Enum.GetNames(typeof(Options)); 

(4)Parse和TryParse:可以將數值和名稱的字串轉換成對應的列舉型別。

Options turnOption = (Options)Enum.Parse(typeof(Options), "Insert");
Options turnOption1 = (Options)Enum.Parse(typeof(Options), "1");
Options tryTurnOption;
Enum.TryParse<Options>("insert", false, out tryTurnOption);


二、位標誌

我們可能需要多個列舉的組合來滿足我們的需要。

位運算是針對二進位制位進行的運算,常用的位運算主要有與(&), 或(|)和非(~)   

e.m:1 & 0 = 0, 1 | 0 = 1, ~1 = 0

要使列舉型別具有位運算的能力,需要加上特性[FlagsAttribute]簡寫[Flags]。有些位處於on狀態,有些處於off狀態。所以通常在定義一個None=0的列舉符號。相對應的值都為2的指數倍。為的是後續的運算。

[Flags]
public enum Options
{
            None=0,
            Insert = 1, //二進位制: 0001
            Update = 2, //二進位制: 0010
            Save = 4,   //二進位制: 0100
            Delete = 8, //二進位制: 1000
            Query = 16  //二進位制:10000
}

許可權列表:

Options hasOps = Options.Insert | Options.Update;
string ops = hasOps.ToString();

我們看到, Options.Insert | Options.Update=0001|0010,“|”與操作:1 | 0 = 1,是二進位制位的運算。我們可以得到結果為:0011。對於這個結果怎麼去應用。

許可權判斷:

if ((hasOps & Options.Insert) == Options.Insert)
{
                Console.WriteLine("Has {0}", Options.Insert);
}

我們可以根據“&”與操作進行許可權判斷,可以表示為:0011&0001=0001,後面0001==0001,符合條件,有Insert許可權。

例項:專案中,有時會進行正則匹配。

string[] imgsArr = Regex.Split(imgsArea, ",", RegexOptions.IgnoreCase | RegexOptions.Multiline);   這句話主要看後面:RegexOptions.IgnoreCase | RegexOptions.Multiline,可以表示為:0001|0010=0011,意思也就是需要同時符合兩個條件,

:RegexOptions.IgnoreCase不區分大小寫匹配 和 RegexOptions.Multiline 多行模式匹配

[Flags]
public
enum RegexOptions { None = 0, IgnoreCase = 1, Multiline = 2, ExplicitCapture = 4, Compiled = 8, Singleline = 16, IgnorePatternWhitespace = 32, RightToLeft = 64, ECMAScript = 256, CultureInvariant = 512, }

 

相關文章