真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何正確的在C#項目中使用枚舉-創(chuàng)新互聯(lián)

本篇文章給大家分享的是有關(guān)如何正確的在C#項目中使用枚舉,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計、網(wǎng)站建設(shè)服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)寶山免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了上千多家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。

枚舉基礎(chǔ)


枚舉類型的作用是限制其變量只能從有限的選項中取值,這些選項(枚舉類型的成員)各自對應(yīng)于一個數(shù)字,數(shù)字默認從 0 開始,并以此遞增。例如:

public enum Days
{
 Sunday, Monday, Tuesday, // ...
}

其中 Sunday 的值是 0,Monday 是 1,以此類推。為了一眼能看出每個成員代表的值,一般推薦顯示地將成員值寫出來,不要省略:

public enum Days
{
 Sunday = 0, Monday = 1, Tuesday = 2, // ...
}

C# 枚舉成員的類型默認是 int 類型,通過繼承可以聲明枚舉成員為其它類型,比如:

public enum Days : byte
{
 Monday = 1,
 Tuesday = 2,
 Wednesday = 3,
 Thursday = 4,
 Friday = 5,
 Saturday = 6,
 Sunday = 7
}

枚舉類型一定是繼承自 byte、sbyte、short、ushort、int、uint、long 和 ulong 中的一種,不能是其它類型。下面是幾個枚舉的常見用法(以上面的 Days 枚舉為例):

// 枚舉轉(zhuǎn)字符串
string foo = Days.Saturday.ToString(); // "Saturday"
string foo = Enum.GetName(typeof(Days), 6); // "Saturday"
// 字符串轉(zhuǎn)枚舉
Enum.TryParse("Tuesday", out Days bar); // true, bar = Days.Tuesday
(Days)Enum.Parse(typeof(Days), "Tuesday"); // Days.Tuesday

// 枚舉轉(zhuǎn)數(shù)字
byte foo = (byte)Days.Monday; // 1
// 數(shù)字轉(zhuǎn)枚舉
Days foo = (Days)2; // Days.Tuesday

// 獲取枚舉所屬的數(shù)字類型
Type foo = Enum.GetUnderlyingType(typeof(Days))); // System.Byte

// 獲取所有的枚舉成員
Array foo = Enum.GetValues(typeof(MyEnum);
// 獲取所有枚舉成員的字段名
string[] foo = Enum.GetNames(typeof(Days));

另外,值得注意的是,枚舉可能會得到非預(yù)期的值(值沒有對應(yīng)的成員)。比如:

Days d = (Days)21; // 不會報錯
Enum.IsDefined(typeof(Days), d); // false

即使枚舉沒有值為 0 的成員,它的默認值永遠都是 0。

var z = default(Days); // 0

枚舉可以通過 Description、Display 等特性來為成員添加有用的輔助信息,比如:

public enum ApiStatus
{
 [Description("成功")]
 OK = 0,
 [Description("資源未找到")]
 NotFound = 2,
 [Description("拒絕訪問")]
 AccessDenied = 3
}

static class EnumExtensions
{
 public static string GetDescription(this Enum val)
 {
  var field = val.GetType().GetField(val.ToString());
  var customAttribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute));
  if (customAttribute == null) { return val.ToString(); }
  else { return ((DescriptionAttribute)customAttribute).Description; }
 }
}

static void Main(string[] args)
{
 Console.WriteLine(ApiStatus.Ok.GetDescription()); // "成功"
}

上面這些我認為已經(jīng)包含了大部分我們?nèi)粘S玫降拿杜e知識了。下面我們繼續(xù)回到文章開頭說的用戶角色存儲問題。

用戶角色存儲問題

我們先定義一個枚舉類型來表示兩種用戶角色:

public enum Roles
{
 Admin = 1,
 Member = 2
}

這樣,如果某個用戶同時擁有 Admin 和 Member 兩種角色,那么 User 表的 Roles 字段就應(yīng)該存 3。那問題來了,此時若查詢所有擁有 Admin 角色的用戶的 SQL 該怎么寫呢?對于有基礎(chǔ)的程序員來說,這個問題很簡單,只要用位操作符邏輯與(‘&')來查詢即可。

SELECT * FROM `User` WHERE `Roles` & 1 = 1;

同理,查詢同時擁有這兩種角色的用戶,SQL 語句應(yīng)該這么寫:

SELECT * FROM `User` WHERE `Roles` & 3 = 3;

對這條 SQL 語句用 C# 來實現(xiàn)查詢是這樣的(為了簡單,這里使用了 Dapper):

public class User
{
 public int Id { get; set; }
 public Roles Roles { get; set; }
}

connection.Query(
 "SELECT * FROM `User` WHERE `Roles` & @roles = @roles;",
 new { roles = Roles.Admin | Roles.Member });

對應(yīng)的,在 C# 中要判斷用戶是否擁有某個角色,可以這么判斷:

// 方式一
if ((user.Roles & Roles.Admin) == Roles.Admin)
{
 // 做管理員可以做的事情
}

// 方式二
if (user.Roles.HasFlag(Roles.Admin))
{
 // 做管理員可以做的事情
}

同理,在 C# 中你可以對枚舉進行任意位邏輯運算,比如要把角色從某個枚舉變量中移除:

var foo = Roles.Admin | Roles.Member;
var bar = foo & ~Roles.Admin;

這就解決了文章前面提到的用整型來存儲多角色的問題,不論數(shù)據(jù)庫還是 C# 語言,操作上都是可行的,而且也很方便靈活。

枚舉的 Flags 特性

下面我們提供一個通過角色來查詢用戶的方法,并演示如何調(diào)用,如下:

public IEnumerable GetUsersInRoles(Roles roles)
{
 _logger.LogDebug(roles.ToString());
 _connection.Query(
  "SELECT * FROM `User` WHERE `Roles` & @roles = @roles;",
  new { roles });
}

// 調(diào)用
_repository.GetUsersInRoles(Roles.Admin | Roles.Member);

Roles.Admin | Roles.Member 的值是 3,由于 Roles 枚舉類型中并沒有定義一個值為 3 的字段,所以在方法內(nèi) roles 參數(shù)顯示的是 3。3 這個信息對于我們調(diào)試或打印日志很不友好。在方法內(nèi),我們并不知道這個 3 代表的是什么。為了解決這個問題,C# 枚舉有個很有用的特性:FlagsAtrribute。

[Flags]
public enum Roles
{
 Admin = 1,
 Member = 2
}

加上這個 Flags 特性后,我們再來調(diào)試 GetUsersInRoles(Roles roles) 方法時,roles 參數(shù)的值就會顯示為 Admin|Member 了。簡單來說,加不加 Flags 的區(qū)別是:

var roles = Roles.Admin | Roles.Member;
Console.WriteLing(roles.ToString()); // "3",沒有 Flags 特性
Console.WriteLing(roles.ToString()); // "Admin, Member",有 Flags 特性

給枚舉加上 Flags 特性,我覺得應(yīng)當視為 C# 編程的一種很好實踐,在定義枚舉時盡量加上 Flags 特性。

解決枚舉值沖突:2 的冪

到這,枚舉類型 Roles 一切看上去沒什么問題,但如果現(xiàn)在要增加一個角色:Mananger,會發(fā)生什么情況?按照數(shù)字值遞增的規(guī)則,Manager 的值應(yīng)當設(shè)為 3。

[Flags]
public enum Roles
{
 Admin = 1,
 Member = 2,
 Manager = 3
}

能不能把 Manager 的值設(shè)為 3?顯然不能,因為 Admin 和 Member 進行位的或邏輯運算(即:Admin | Member) 的值也是 3,表示同時擁有這兩種角色,這和 Manager 沖突了。那怎樣設(shè)值才能避免沖突呢?既然是二進制邏輯運算“或”會和成員值產(chǎn)生沖突,那就利用邏輯運算或的規(guī)律來解決。我們知道“或”運算的邏輯是兩邊只要出現(xiàn)一個 1 結(jié)果就會 1,比如 1|1、1|0 結(jié)果都是 1,只有 0|0 的情況結(jié)果才是 0。那么我們就要避免任意兩個值在相同的位置上出現(xiàn) 1。根據(jù)二進制滿 2 進 1 的特點,只要保證枚舉的各項值都是 2 的冪即可。比如:

1:  00000001
2:  00000010
4:  00000100
8:  00001000


再往后增加的話就是 16、32、64...,其中各值不論怎么相加都不會和成員的任一值沖突。這樣問題就解決了,所以我們要這樣定義 Roles 枚舉的值:

[Flags]
public enum Roles
{
 Admin = 1,
 Member = 2,
 Manager = 4,
 Operator = 8
}

不過在定義值的時候要在心中小小計算一下,如果你想懶一點,可以用下面這種“位移”的方法來定義:

[Flags]
public enum Roles
{
 Admin = 1 << 0,
 Member = 1 << 1,
 Manager = 1 << 2,
 Operator = 1 << 3
}

一直往下遞增編值即可,閱讀體驗好,也不容易編錯。兩種方式是等效的,常量位移的計算是在編譯的時候進行的,所以相比不會有額外的開銷。

以上就是如何正確的在C#項目中使用枚舉,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


當前標題:如何正確的在C#項目中使用枚舉-創(chuàng)新互聯(lián)
文章地址:http://weahome.cn/article/shihi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部