测试篇 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();
}

(完)

posted @ 2019-12-13 10:14  惊惊  阅读(1839)  评论(0编辑  收藏  举报