枚举和位标志

DoubleJ

枚举是程序中经常使用的数据类型,使用枚举,可以让代码具有更高的可读性,易扩展性以及更容易编写等有点。同时枚举还是强类型,提升程序的健壮性。

例如要对颜色进行区分,在不使用枚举时,可能制定约定:定义若干个值: 0,1,2,3分别代表红,黄,蓝,绿四种颜色,但是这会增加程序的维护成本。

使用枚举能够很清晰的表明代码的意图
enum Color
{
    Red,    //红
    Yellow, //黄
    Blue,   //蓝
    Green   //绿
}
枚举值的类型

枚举值的类型可以是: byte,sbyte,short,ushort,int,uint,long,ulong。默认类型是int,自定义其它类型的枚举值类型

enum Color : byte {}
//获取枚举值类型(输出System.Byte)
System.Console.WriteLine(System.Enum.GetUnderlyingType(typeof(Color)));
获取所有枚举值
foreach (var item in (Color[])System.Enum.GetValues(typeof(Color)))
    System.Console.WriteLine(item);

结果
image.png

位标志

位标志是一种特殊的枚举类型,枚举值的存在是互斥的,位标志可以理解成是一种组合的列表,如文件的属性可以有隐藏与只读等多种。

位标志的声明

[Flags] //添加Flags标记便可声明一个位标志
enum Action
{
    None = 0,
    Walk = 0x0001,
    Run = 0x0002,
    Speak = 0x0004
}
位标志的实例使用
//声明一个行为
var action = Action.None;
//判断该行为是否能走 输出false
Console.WriteLine((action & Action.Walk) != 0);
Console.WriteLine((action & Action.Walk) == Action.Walk);
//添加行走和奔跑行为
action = action | Action.Walk | Action.Run;
Console.WriteLine((action & Action.Walk) != 0);//true
Console.WriteLine((action & Action.Run) != 0); //true
//删除走的行为
action = action &~ Action.Walk;
Console.WriteLine((action & Action.Walk) != 0);//false
Console.WriteLine((action & Action.Run) != 0); //true

使用HasFlag方法判断枚举实例中是否存在某个标志

var action = Action.Run | Action.Speak;
Console.WriteLine(action.HasFlag(Action.Walk));//false
Console.WriteLine(action.HasFlag(Action.Run)); //true

*由于HasFlag接受一个Enum类型的参数,所以使用该方法需要装箱,产生一次内存分配

调用ToString方法能更加直观的看到位标志的组合

var action = Action.Run | Action.Speak; //0x0006
//由于存在[Flags],ToString方法便会将它视为一组位标志而不是单独的数值,所以输出 Run, Speak
//如果删除[Flags],程序将输出 6
Console.WriteLine(action.ToString());
存在位标志时ToString的工作流程
  1. 获取枚举类型定义的数值集并按降序排列
  2. 每个数值将会与枚举实例的值进行“按位与”计算,假设结果等于该数值,与该数值关联的字符串便会追加到输出字符串中,对应的位会被关闭(设置为0)
  3. 重复第2步,直到检查完枚举实例中的所有位
使用扩展方法向枚举中添加方法
public static Action Set(this Action flags, Action setAction)
{
    return flags | setAction;
}

//用例
var action = Action.Walk;
//输出 Walk
Console.WriteLine(action.ToString());
action = action.Set(Action.Run);
//输出 Walk, Run
Console.WriteLine(action.ToString());
阅读 159
1 声望
2 粉丝
0 条评论
1 声望
2 粉丝
宣传栏