成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

細說C#中有意思的枚舉:轉換、標志和屬性

原創
開發 后端
枚舉是 C# 中最有意思的一部分,大部分開發人員只了解其中的一小部分,甚至網上絕大多數的教程也只講解了枚舉的一部分。那么,我將通過這篇文章向大家具體講解一下枚舉的知識。我將從大家都了解的部分開始講解,然后再講解大家所不知道的或者了解很少的部分。

[[314690]]

【51CTO.com原創稿件】枚舉是 C# 中最有意思的一部分,大部分開發人員只了解其中的一小部分,甚至網上絕大多數的教程也只講解了枚舉的一部分。那么,我將通過這篇文章向大家具體講解一下枚舉的知識。我將從大家都了解的部分開始講解,然后再講解大家所不知道的或者了解很少的部分。

一、基礎知識

枚舉是由開發人員聲明的一種 值類型 ,它在編譯時就聲明了一種 具名常量值 。使用枚舉可以使我們的代碼簡單易讀,我們先來看一下兩個代碼段:

  1. // 代碼段 1 
  2. void Method(int country) 
  3.     switch (country) 
  4.     { 
  5.         case 0: 
  6.             // more code 
  7.             break; 
  8.         case 1: 
  9.             // more code 
  10.             break; 
  11.         case 2: 
  12.             // more code 
  13.             break; 
  14.         case 3: 
  15.             // more code 
  16.             break; 
  17.         default
  18.             // more code  
  19.             break; 
  20.     } 
  21.  
  22. // 代碼段 2 
  23. void Method(Country country) 
  24.     switch (country) 
  25.     { 
  26.         case Country.CN: 
  27.             // more code 
  28.             break; 
  29.         case Country.JP: 
  30.             // more code 
  31.             break; 
  32.         case Country.UK: 
  33.             // more code 
  34.             break; 
  35.         case Country.USA: 
  36.             // more code 
  37.             break; 
  38.         default
  39.             // more code  
  40.             break; 
  41.     } 

從上面的兩個代碼段我們可以看到兩者有明顯的區別。第一段代碼中的 case 值我們幾乎完全不知道代表了什么是什么意思,但是第二段代碼我們使用了枚舉,通過 case 值馬上就可以知道所要表達的意思。同樣利用枚舉值替代布爾值也可以改善代碼的可讀性,例如我們要開發控制臺燈打開關閉的程序,代碼可以這么寫 LightOperating(True) ,但是這種代碼我們無法看出具體要干什么,現在我們將代碼改動一下 LightOperating(Light.On) 。經過修改代碼就很容易看出所要表達的意思。

1.枚舉定義與取值

定義枚舉有兩種方式,分別是普通方式和自定義方式。不管使用哪種方式都需要用的關鍵字 enum 來標識這個類型為枚舉類型,并且枚舉值都是作為整數常量來實現的。下面我們就來看一下這兩種方式怎么定義枚舉的。普通方式是我們經常用到的,也是默認的方式。這種方式很簡單,代碼如下:

  1. enum Country 
  2.     CN, 
  3.     UK, 
  4.     JP, 
  5.     USA 

在上面的代碼段中我們定義了一個國家枚舉,第一個枚舉值對應的整數常量是 0 ,第二個枚舉值對應的整數常量是 1 ,以此類推后面的枚舉值分別對應的整數常量是 23 。但是在部分情況下我們需要自定義枚舉值對應的整數常量,這個時候我們就需要用到自定義的方式。自定義方式又稱為為枚舉值顯式賦值,它的方法如下所示:

  1. enum Country 
  2.  { 
  3.      CN = 3, 
  4.      UK, 
  5.      JP = 70, 
  6.      USA = 67 
  7.  } 

我們在代碼中將第一個枚舉值對應的整數常量設置為了 3 ,這時第二個枚舉值的整數常量就不是 1 了,而是 4 ,因為當枚舉值沒有顯示賦值時,將會按照上一個枚舉值對應的整數值加 1 來作為自己本身對應的整數值。最后兩個枚舉值因為顯式賦值了因此對應的整數值就是所賦值的數值。 枚舉取值也很簡單,只需要 枚舉名.枚舉值 即可,例如 Country.UK

Tip:這里我提幾點建議:

  • 枚舉值的名稱不應包含枚舉名稱;

  • 枚舉名稱應以單數的形式出現(除了屬性)。

2.枚舉的類型

到目前為止,我們定義枚舉類型使用的基礎類型 int 類型,但是枚舉不僅僅可以使用 int 類型,還可以使用除了 char 類型之外的所有基礎類型。我們可以使用繼承語法來指定其他類型。

  1. enum Country:short 
  2.  { 
  3.      CN = 3, 
  4.      UK, 
  5.      JP = 70, 
  6.      USA = 67 
  7.  } 

上面代碼中我們顯式定義了枚舉所使用的基礎類型為 short 。這里雖然使用了繼承語法但是并沒有建立繼承關系,所有的枚舉基類都是 System.Enum ,這些類都是密封類,無法從現有的枚舉類型派生出新的成員。 對于枚舉類型的變量,值不限于聲明中命名的值,因此值能轉換成基礎類型,那么就能轉換為枚舉類型。之所以這么設計是因在以后的 API 中有很大的可能在不破換老版本的同時為枚舉添加新的值。但是這其中也存在一個缺陷,枚舉允許在運行時分配未知的值,對于這一點我們在開發時需要考慮到。并且在后期向枚舉中添加新的枚舉值時應將其添加到所有枚舉值的后面,或者顯示指定枚舉值對應的數值,這樣才能避免因添加新值導致枚舉類型中的枚舉值對應的數值改變。

Tip:在開發中我們應該盡量使用 int 作為枚舉的基礎類型,除非因性能問題或互操作方面的考慮時才會考慮使用較小的類型。

二、枚舉轉換

枚舉轉換主要涉及到了枚舉與枚舉的轉換、枚舉與數字和字符串的轉換。

1.枚舉之間轉換

首先我要說明的是在 C# 中不支持不同枚舉數組之間的直接轉換,所以如果想要實現不同枚舉數組之間的轉換我們可以利用 CLR 寬松的賦值兼容性這一特點來進行轉換,需要轉換的兩個枚舉必須具有相同的基礎類型。同樣,我們通過一個例子來看一下具體實現方法。

  1. static void Main(string[] args) 
  2.  { 
  3.      CountryAllName[] can = (CountryAllName[])(Array)new Country[4]; 
  4.  } 
  5. enum Country 
  6.  { 
  7.      CN, 
  8.      UK, 
  9.      JP, 
  10.      USA 
  11.  } 
  12.  enum CountryAllName 
  13.  { 
  14.      China, 
  15.      UnitedKingdom, 
  16.      Japan, 
  17.      UnitedStates 
  18.  } 

在使用這種方法時有可能會出現意外的錯誤或結果,并且相關開發規范中并沒有說這種方式每次都起作用,因此我不建議這么使用,除非在一些極端場景中。

2.枚舉和字符串之間轉換

枚舉轉換為字符串可以直接使用 ToString() 方法, 枚舉值 ToString 后會直接輸出枚舉值標識符的字符串形式,例如 Country.CN.ToString() 得到的結果是字符串 CN 。當然,你也可以利用 Enum.GetNamesEnum.GetName 方法來獲取。下面我簡單來講解一下這兩個方法的使用。 

  • GetNames GetNames 方法需要傳入一個枚舉類型,返回值是一個字符串數組。例如需要獲取到 Country 的第二個國家,那么就可以這么來寫 Enum.GetNames(typeof(Country))[1],返回結果是 UK 。

  • GetName GetName 方法返回的是一個字符串,這個字符串就是需要獲取的指定枚舉值的字符串形式。同樣我們獲取第二個國家,Enum.GetName(typeof(Country),1) ,返回的值同樣是 UK 。 字符串轉換為枚舉也很簡單,同樣用到了 Enum 基類的一個靜態方法 Parse ,例如我們將 JP 轉換為枚舉 Country 的枚舉值可以這么做 (Country)Enum.Parse(typeof(Country),"JP") 。這里有一點需要注意,TryParse 方法是在 .net 4.0 才出現的,因此如果要在 .net 4.0 以下版本中將字符串轉換為枚舉時,需要進行恰當的錯誤處理防止字符串不存在與枚舉類型中的枚舉值中。

Tip:字符串向枚舉轉換不可本地化,如果必須本地化,就必須是那些對上層用戶不可見的消息。因此在實際開發中應該盡量避免枚舉和字符串之間的轉換。

3.枚舉和數字之間轉換

枚舉轉換為數字我們可以使用強轉,例如 (int)Country.CN 返回結果是 0 。從數字轉換為枚舉我們有兩種方法,一種是使用強轉,另一種是使用 Enum 的靜態方發 ToObject

  • 強轉 強轉就比較簡單了,Country country = (Country)2

  • ToObject ToObject 方法需要傳入枚舉類型和需要轉換的數字,例如 Country country = (Country)Enum.ToObject(typeof(Country),2)

4.注意

字符串轉換為枚舉和數字轉換為枚舉都必須先進行判斷所要轉換的值是否包含在枚舉中,判斷的方法也很簡單只需要調用 Enum 的靜態方法 IsDefined 即可,例如我要將 0 和 HK 轉換為枚舉,代碼如下:

  1. Type type = typeof(Country); 
  2.  if(Enum.IsDefined(type,0)) 
  3.  { 
  4.      Enum.ToObject(type, 0); 
  5.  } 
  6.  if(Enum.IsDefined(type,"HK")) 
  7.  { 
  8.      Enum.Parse(typeof(Country), "HK"); 
  9.  } 

上述代碼中只有 0 會成功轉換為枚舉值 CN ,因為 0 所對應的枚舉值是 CN ,而 HK 并沒有在枚舉中。

三、標志與屬性

這一小節我們來講解一下標志與屬性,標志he和屬性屬于在開發中用的比較少,并且大部分程序員了解的也不多。

1.標志

在開發中有時我們希望能對枚舉進行組合使用來表示復合值,那么這時我們就需要定義標志枚舉了,標志枚舉的名稱為復數形式,代表了一個標志的集合。一般我們會使用按位或操作符鏈接枚舉值,使用 HasFlags 方法或者按位與操作符來判斷特定的位是否存在。比較經典的標志枚舉是位于 System.IO 命名空間中的 FileAttributes 標志枚舉,它列出了文件的所有屬性,比如只讀、隱藏、所在磁盤等等,它所包含的所有枚舉值皆可相互組合,例如一個文件既是隱藏文件又是只讀文件。定義標志枚舉的方法如下:

  1. [Flags] 
  2. enum WeekDays 
  3.  { 
  4.      Monday = 1, 
  5.      Tuesday = 2, 
  6.      Wednesday = 4, 
  7.      Thursday = 8, 
  8.      Friday = 16, 
  9.      Saturday = 32, 
  10.      Sunday = 64 
  11.  } 

在上面的代碼中你會發現一個規律,每個枚舉值對應的整數值都是 2的n次方,這是為什么呢。在標志枚舉中要求多個枚舉值相互組合后的結果不能包含在標志枚舉中,并且基于按位運算的特性可以很方便的使用位運算符來計算一個枚舉值是否包含了另外一個枚舉值,這在權限系統中相當有用。

2.屬性

枚舉值上同樣也可以使用屬性,例如我們需要打印輸出枚舉值的中文名,我們就可以通過屬性的形式進行設置,首先我們需要定義一個屬性:

  1. public class EnumChineseAttribute : Attribute 
  2.  { 
  3.      private string m_strDescription; 
  4.      public EnumChineseAttribute(string chineseName) 
  5.      { 
  6.          m_strDescription = chineseName; 
  7.      } 
  8.  
  9.      public string Description 
  10.      { 
  11.          get { return m_strDescription; } 
  12.      } 
  13.  } 
  14.  enum Country 
  15.  { 
  16.      [EnumChinese("中國")] 
  17.      CN, 
  18.      [EnumChinese("英國")] 
  19.      UK, 
  20.      [EnumChinese("日本")] 
  21.      JP, 
  22.      [EnumChinese("美國")] 
  23.      USA 
  24.  } 
  25.  static void Main(string[] args) 
  26.  { 
  27.      Country country = Country.CN; 
  28.      FieldInfo fieldInfo = country.GetType().GetField("CN"); 
  29.      object[] attribArray = fieldInfo.GetCustomAttributes(false); 
  30.      EnumChineseAttribute attrib = (EnumChineseAttribute)attribArray[0]; 
  31.      Console.WriteLine(attrib.Description); 
  32.      Console.Read(); 
  33.  } 

通過上面的代碼我們就能獲取到 CN 對應的中文名稱了,這段代碼并沒有進行進一步優化,在實際項目中必須進行封裝和優化。

四、小結

這篇文章主要講解了枚舉相關的知識,內容有點瑣碎,但是在實際開發中還是比較實用的。文章中我所提到的要點和規定在實際開發中已經經過驗證,各位讀者可以直接拿來使用。

作者簡介:

朱鋼,筆名喵叔,國內某技術博客認證專家,.NET高級開發工程師,7年一線開發經驗,參與過電子政務系統和AI客服系統的開發,以及互聯網招聘網站的架構設計,目前就職于一家初創公司,從事企業級安全監控系統的開發。

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

 

責任編輯:龐桂玉 來源: 51CTO
相關推薦

2009-08-26 17:53:31

C# DropDown

2021-03-25 06:12:55

SVG 濾鏡CSS

2022-08-15 22:34:47

Overflow方向裁切

2022-06-15 07:21:47

鼠標指針交互效果CSS

2022-07-11 13:09:26

mmapLinux

2020-12-12 13:50:16

云開發

2021-01-27 13:54:05

開發云原生工具

2018-06-24 16:39:28

Tomcat異常線程

2017-08-01 00:52:07

kafka大數據消息總線

2013-08-28 09:46:09

Debian LinuLinux發行版

2012-06-19 16:49:19

Web開發

2010-04-09 11:24:59

Oracle 排序

2012-05-22 10:12:59

jQuery

2021-11-17 10:45:58

Chrome 95新特性前端

2015-10-28 13:57:29

融合架構華三UIS

2021-04-09 08:23:30

Css前端加載動畫

2015-09-17 17:49:13

華三/UIS

2012-04-12 15:14:31

idf2012英特爾

2023-05-15 09:16:18

CSSCSS Mask

2022-08-23 08:01:09

CSS前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 麻豆久久久久久 | 超碰成人av | 久久精品中文字幕 | 国产午夜精品理论片a大结局 | 亚洲一区二区三区在线免费 | 日韩视频一区 | 国产一区二区在线免费观看 | 黄色片在线免费看 | 精品国产伦一区二区三区观看说明 | av黄色网 | 一区视频| 在线第一页 | 四虎影院新地址 | 啪啪免费网站 | 最新av在线网址 | 精品在线一区 | 亚洲精品在线免费看 | a视频在线观看 | 国产www成人 | 免费v片| 久久久久久综合 | 色毛片 | 在线观看www| 精品亚洲一区二区三区四区五区高 | 色婷婷综合久久久中字幕精品久久 | 综合精品 | 亚洲免费精品一区 | 在线91| 午夜视频一区二区三区 | 亚洲综合精品 | 国产成人福利在线观看 | 亚洲福利一区 | 久久久久久亚洲精品 | 青青草国产在线观看 | 四色永久| 久久久久亚洲精品中文字幕 | 热久久免费视频 | 538在线精品| 欧美一级二级三级视频 | 天天躁人人躁人人躁狂躁 | 精品亚洲一区二区 |