测试篇 c#枚举类型怎么用
枚举类型怎么写
枚举类型只是一个值,只是用了名称约束,更具象而已.
既然它是一个值,就有一些相关的概念,包括二次方特性,位运算.
有很多人写的教程都没有像我一样用代码简单说明...
所以我这里贴出来一下,免得我忘记...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
namespace EnumTest;
public static class Program {
// 定义枚举类型,利用二次方才能按位判断
// 特性Flags是为了.ToString()显示名称而不是值
// 继承是为了限制序列化字节大小
[Flags]
public enum ServicePut : byte {
[Description("未分配")]
None = 0,
[Description("验证状态")]
Verify = 1,
[Description("检查服务")]
Check = 1 << 1,
[Description("安装服务")]
Install = 1 << 2,
[Description("启动服务")]
Start = 1 << 3,
[Description("卸载服务")]
Uninstall = 1 << 4,
[Description("停止服务")]
Stop = 1 << 5,
[Description("备用状态1")]
A = 1 << 6,
[Description("备用状态2")]
B = 1 << 7,
}
// 利用按位与&,比较位和掩码位都是1,则输出1.
// 也就是如果"包含"则执行,这样就可以执行很多个动作.
// 这样写还有一个好处,聚合了业务,不用分散写.
public static void DeployService(ServicePut sp) {
if (sp == ServicePut.None) {
Console.WriteLine("未分配");
return;
}
if ((sp & ServicePut.Verify) == ServicePut.Verify)
Console.WriteLine("验证状态");
if ((sp & ServicePut.Check) == ServicePut.Check)
Console.WriteLine("检查服务");
if ((sp & ServicePut.Install) == ServicePut.Install)
Console.WriteLine("安装服务");
if ((sp & ServicePut.Start) == ServicePut.Start)
Console.WriteLine("启动服务");
if ((sp & ServicePut.Uninstall) == ServicePut.Uninstall)
Console.WriteLine("卸载服务");
if ((sp & ServicePut.Stop) == ServicePut.Stop)
Console.WriteLine("停止服务");
}
// 主函数调用
// 利用按位或,使得它能执行了两个动作
static void Main(string[] args) {
DeployService(ServicePut.Install | ServicePut.Start);
Console.ReadKey();
}
}
原理
转为二进制:
Convert.ToString(2, 2);
Convert.ToString(4, 2);
Convert.ToString(6, 2);
在C#输入二进制字面量是:
0b0001
左移,二次幂:
0b0001 << 1;
0b0010 ←结果:这样就*2了==2
再来一次:
0b0010 << 1;
0b0100 ←结果:又再次*2了==4
按位或,有一位是1则是1.
0b0010 = 2
0b0100 = 4
_____________ | 按位或,进行二进制计算(跟小学加法竖式一样),
0b0110 = 6 ←结果
是不是很简单?
而按位与&就是比较位和掩码是否为1,有一种"包含"的意思.
0b0110 ←比较
0b0010 & ←掩码
___________
0b0010 ←结果,结果和掩码是一样,则含有.
位运算技巧
按位或和左移配合
能够组合两个数字,例如大版本号.小版本号.
int32是32bit(四字节),
前16bit叫高位,后16bit叫低位.可以想象成两个盒子.
为什么是16?因为折半而已.
你也可以是32/16/8/4,也可以是诡异数字.
int a = 1; // 我们平时输入1是在低位上.
a = a << 16; // 左移它,就推到高位上面,推过去之后低位全是0.
a = a | 2; // 按位或,因为低位是0,就组合了两个数字了.
0b00000000 00000001(高) 00000000 00000010(低) ←结果
↑第一位是符号位
负数转正数
非绝对值,常用于hashcode
int a = -99;
Console.WriteLine(Convert.ToString(a, 2));
a = a & 0x7FFFFFFF; // int32除了符号位全1.
Console.WriteLine(a);
var str = Convert.ToString(a, 2);
Console.WriteLine(str);
Console.WriteLine(str.Length);
遍历枚举
1.通过枚举的名称获取值.
2.通过值获取名称.
但是只要知道了Enum.GetValues()的操作就可以了
// 遍历这个枚举类型
foreach (var item in Enum.GetValues(typeof(ServicePut))) {
// 获取枚举的每项的名称
if (item.ToString() == "Install") {
// 强转成枚举类型
var e = (ServicePut)item;
return e;
}
}
// 构造Map
// 通过名称找枚举值
var nameMap = Enum.GetNames(typeof(ServicePut))
.ToDictionary(name => name,
name => (ServicePut)Enum.Parse(typeof(ServicePut), name));
// 通过枚举值找名称
var enumMap = Enum.GetValues(typeof(ServicePut))
.Cast<ServicePut>()
.ToDictionary(key => key,
key => Enum.GetName(typeof(ServicePut), key));
通过Desc找枚举值
public static void Main() {
var servicePutDescriptions = Enum.GetValues(typeof(ServicePut))
.Cast<ServicePut>()
.ToDictionary(
value => value.GetDescription(),
value => value
);
foreach (var pair in servicePutDescriptions)
{
Console.WriteLine($"Description: {pair.Key}, ServicePut: {pair.Value}");
}
}
private static string GetDescription(this Enum value) {
var fieldInfo = value.GetType().GetField(value.ToString());
var attribute = (DescriptionAttribute)Attribute.GetCustomAttribute(
fieldInfo, typeof(DescriptionAttribute));
return attribute != null ? attribute.Description : value.ToString();
}
(完)