开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第21天,点击查看活动详情
C#值类型中的枚举类型,我们需要了解它与int、string类型的转换,以及使用[Flags]
特性启用位枚举的方式,在选项组合中非常实用。
值类型
枚举类型
枚举类型转换
Enum、Int和String的互相转换。
Enum ——> String
Object.ToString()
:获取字符串
Season.Spring.ToString(); // "Spring"
Enum
的静态方法GetName
或GetNames
Enum.GetName(typeof(Season),1); // Summer
Enum.GetName(typeof(Season), Season.Summer); // Summer
Enum.GetNames(typeof(Season)
获取枚举(成员)的字符串数组。
String ——> Enum
- Enum的静态方法
Parse
或TryParse
var season=Enum.Parse(typeof(Season),"Autumn",ignoreCase:true);
var result = Enum.TryParse(typeof(Season), "Autumn", ignoreCase: true, out object? season1);
var result2 = Enum.TryParse("Autumn", ignoreCase: true, out Season season2); // 推荐
Enum ——> Int
- 强制类型转换
枚举的基类型是除 Char 外的整型,所以可以进行强制转换。
Console.WriteLine((int)Season.Summer);
Console.WriteLine((byte)Season.Summer);
Int ——> Enum
- 强制将整型转换成枚举类型
var season = (Season)2;
Enum
的静态方法ToObject
var season3 = Enum.ToObject(typeof(Season),3);
Console.WriteLine(season3); // Winter
ToObject()
得到的是object类型。
Enum.IsDefined
判断某个整型或名称是否定义在枚举中
Console.WriteLine(Enum.IsDefined(typeof(Season), 1)); // True
Console.WriteLine(Enum.IsDefined(typeof(Season), "Autumn")); // True
[Flags] 特性的位枚举/标志枚举
HasFlag()
方法可以判断当前实例是否设置了标志位(或 位域)。
位枚举的介绍和声明
[Flags]
特性可以将枚举类型转变为位标记(bit flags
)的枚举。
其本质,是将枚举值对应到二进制数值位上,比如第一个成员值对应为0,第二个成员值对应为1,第三个对应为2 .... 每个二进制位表示一个枚举值(2的二次幂),如下所示:
[Flags]
public enum Days
{
None = 0b_0000_0000, // 0
Monday = 0b_0000_0001, // 1
Tuesday = 0b_0000_0010, // 2
Wednesday = 0b_0000_0100, // 4
Thursday = 0b_0000_1000, // 8
Friday = 0b_0001_0000, // 16
Saturday = 0b_0010_0000, // 32
Sunday = 0b_0100_0000, // 64
Weekend = Saturday | Sunday
}
这就是位枚举/标志枚举,由于每个值表示一个二进制位,所以,位枚举可以执行 按位或|
、按位与&
操作,组合不同的取值。比如上面的Weekend
就是Saturday | Sunday
的组合值。
位枚举的主要应用就是选择的组合(复合选项取值)。
[Flags]
特性指定位枚举时,应该同时指定枚举的整数值,类似上面的写法,因为默认枚举值是从0按顺序递增的。
如果不指定整数值,默认的位枚举会表示为如下:
[Flags]
public enum Permission
{
Unknown, // 0
Create, // 1
Read, // 2
Update, // Permission.Create | Permission.Read -- 3
Delete, // 4
}
如果要指定枚举取值,还可以直接赋值十进制值 0,1,2,4,8....,或者使用 按位左移操作符<<
,对二进制的个位1进行左移:
[Flags]
public enum Permission
{
Unknown = 0, // 也可以写成0x00或0
Create = 1 << 0, // 0x01或1
Read = 1 << 1, //0x02或2
Update = 1 << 2, //0x04或4
Delete = 1 << 3, //0x08或8
ReadWrite= Permission.Read | Permission.Update
}
位枚举实例
以Permission
位枚举为例,下面通过 位与&
、或|
等操作,查看如何组合和管理 位枚举 的不同取值。
- 1、
|
(组合): 给用户创建、读取,修改和删除的权限
var permission = Permission.Create | Permission.Read | Permission.Update | Permission.Delete;
- 2、
~
按位取反再&
与(交叉):去掉用户的修改和删除权限
permission = permission & ~Permission.Update;
permission = permission & ~Permission.Delete;
- 3、
|
在原来枚举实例上,增加位枚举取值
permission = permission | Permission.Update;
- 4、
&
与:判断是否有某个位枚举值。
判断用户是否有创建的权限
var isCreate = (permission & Permission.Create)!=0;
//或者
var isCreate = (permission & permission.Create)==permission.Create;
parmission
枚举的值如果为 0+1+4=5
,parmission.ToSting()
将变成"Create, Update"
。
在引用COM组件时,也需要用到位枚举。
不加
[Flags]
特性的普通枚举实例也可以按位操作,那就是枚举实例对应的整数值的位操作
了。
位枚举的位操作【总结】
- add 添加
a|b
- remove 删除
a & ~b
- check 检查是否存在
(a & b ) != 0;
- reverse 翻转(有就删,无就加)
a ^ b