文章目录
- 枚举
- 为什么要有枚举?
- 枚举的性质
- 设置默认类型和显式设置成员的值
- 位标志(重要)
- 位标记是什么及作用
- 位标志周边知识
- HasFlag判断是否有该功能
- 枚举前面加Flags的好处
- 关于枚举的更多知识
- using static简化代码
- 获取枚举成员的字面量
枚举
为什么要有枚举?
为了增加代码的可读性以及可维护性,增加了枚举这一种值类型(直接在栈上存储数据).
如在红黑树中给节点赋初始值,直接赋值0/1可读性太差.
枚举一个Color类型,RED在代表红色节点的同时又表示0,大大增加代码的可读性.
enum Color {RED,BLACK
}class Node {//...public Node(int key) {Key = key;NodeColor = Color.RED; // 默认新插入的节点是红色}
}
枚举的性质
enum TrafficLight {RED, //值为0YELLOW,GREEN
}
1.每个成员之间以逗号分隔,
2.每个成员默认表示的值从0开始.后面的值比前面的值大1
3.每个成员的默认类型是int
4.成员的名字不能重复
namespace shh
{enum TrafficLight{GREEN,RED,YELLOW,}class Program{static void Main(string[] args){TrafficLight t1 = TrafficLight.RED;//创建变量t1,并用枚举成员RED初始化Console.WriteLine(t1);}}
}
默认情况下打印t1显示的是t1的字面值RED,而不是他的实际值1.
如果要得到他的实际值,用int强转就行.
设置默认类型和显式设置成员的值
修改默认类型,在枚举类型后面加冒号,然后设置新的默认类型.
enum TrafficLight:uint{GREEN,RED,YELLOW,}
显式设置值
namespace shh
{enum TrafficLight:uint{GREEN=100,RED,YELLOW,}class Program{static void Main(string[] args){TrafficLight t1 = TrafficLight.RED;Console.WriteLine((int)t1);}}
}
先设置GREEN的值为100,因为后面的值是前面的值+1,所以RED=101.
位标志(重要)
位标记是什么及作用
位标记:用数据的二进制位来表示功能的开/关
我用下面的文件操作来举例
Write表示对文件进行写操作,二进制 0001
Read表示对文件进行读操作,二进制 0010.
每个值都是2的幂,然后就可以把他们组合起来形成唯一的值.
ReadWrite是Read和Write的组合
[Flags]enum FileOperations{None=0x0, //0x是十六进制的意思Write=0x1,Read=0x2,Execute=0x8,ReadWrite = Read|Write}
位标志在文件权限管理中非常常见,可以通过单个整数来表示多种不同的权限.
FileOperations F1 = FileOperations.None;FileOperations F2 = FileOperations.ReadWrite;
既节省性能,又增强代码的可读性
位标志周边知识
HasFlag判断是否有该功能
class Program{static void Main(string[] args){FileOperations F1 = FileOperations.ReadWrite;bool Test = F1.HasFlag(FileOperations.Execute);if(Test == false){Console.WriteLine("Test can not Execute");}}}
变量F1没有执行权限.
另外一种判断方法:
static void Main(string[] args){FileOperations F1 = FileOperations.ReadWrite;bool Test = (F1 & FileOperations.Write)==FileOperations.Write;if(Test == true){Console.WriteLine("Test can Write");}}
计算过程:(二进制位)
F1:0011
FileOperations.Write:0001
按位与(&)之后:0001
枚举前面加Flags的好处
class Program{static void Main(string[] args){FileOperations F1 = FileOperations.ReadWrite| FileOperations.Execute;Console.WriteLine(F1.ToString());}}
没去Flags:
去掉Flags:
Tostring:与枚举的成员匹配,成功的话返回字符串名称
没有Flags,编译器直接拿11去找枚举成员里面是否有匹配的.没有找到,打印11.
Flags相当于一个信号,告诉编译器枚举成员之间是可以进行组合的,然后他就拿着11去对应两个分开的成员.
关于枚举的更多知识
using static简化代码
using System;
using System.Collections.Generic;
using static shh.TrafficLight;
namespace shh
{enum TrafficLight{GREEN=100,RED,YELLOW,}class Program{static void Main(string[] args){Console.WriteLine($"{(int)RED}");}}
}//输出:101
using static shh.TrafficLight;扩展TrafficLight这个静态类,使得在函数体内不需要用 类名.成员 来访问
简化:TrafficLight.RED ==> RED
从中我们也可以看出,枚举类型属于静态类型,所以我们不用创建变量也能使用.顺便说一下,我们的Main主函数也是静态的.
namespace shh
{enum TrafficLight{GREEN = 100,RED,YELLOW,}class Program{static void Main(string[] args){Console.WriteLine(TrafficLight.GREEN);}}}
获取枚举成员的字面量
GetNames方法:调用Enum类型的GetNames方法,传参(用typeof来获取枚举类型),最后foreach遍历取得枚举成员.
namespace shh
{enum TrafficLight{GREEN=100,RED,YELLOW,}class Program{static void Main(string[] args){foreach (var name in Enum.GetNames(typeof(TrafficLight))) Console.WriteLine(name);}}
}//输出
//GREEN
//RED
//YELLOW