开源 - Ideal库 - 常用枚举扩展方法(一)

今天和大家享一些关于枚举操作相关的常用扩展方法。

我们平时用的比较多的是正常枚举,同时还有加[Flags]特性的位标志枚举,因此以下所有扩展方法同时适用正常枚举以及位标志枚举。

我们首先定义两种枚举用于下面扩展方法测试适用,代码如下:

csharp 复制代码
//正常枚举
internal enum StatusEnum
{
    [Description("正常")]
    Normal = 0,
    [Description("待机")]
    Standby = 1,
    [Description("离线")]
    Offline = 2,
    Online = 3,
}
//位标志枚举
[Flags]
internal enum TypeFlagsEnum
{
    [Description("Http协议")]
    Http = 1,
    [Description("Udp协议")]
    Udp = 2,
    [Description("Http协议,Udp协议")]
    HttpAndUdp = 3,
    [Description("Tcp协议")]
    Tcp = 4,
}

01、根据枚举名称转换成枚举

该方法接收枚举名称字符串,并转为对应枚举,转换失败则返回空。

首先会校验字符串是否为整数值类型字符串,如果是则直接返回空,因为枚举名称不可能是整数类型字符串。

然后调用TryParse方法进行转换,具体代码如下:

csharp 复制代码
//根据枚举名称转换成枚举,转换失败则返回空
public static T? ToEnumByName<T>(this string name) where T : struct, Enum
{
    //如果为整数类型字符串,则直接返回空
    if (int.TryParse(name, out _))
    {
        return default;
    }
    //转换成功则返回结果,否则返回空
    if (Enum.TryParse<T>(name, out var result))
    {
        return result;
    }
    return default;
}

下面我们对其进行详细的单元测试,分别针对正常枚举和位标志枚举两种情况测试,具体用例如下:

(1) 正常枚举名称字符串,成功转换成枚举;

(2) 不存在的枚举名称字符串,返回空;

(3) 整数类型的字符串,返回空;

(4) 正常位标志枚举名称字符串,成功转换成枚举;

(5) 不存在的位标志枚举名称字符串,返回空;

(6) 正常的位标志枚举名称组合字符串,成功转换成枚举;

(7) 不存在的位标志枚举名称组合字符串,返回空;

位标志枚举名称组合字符串是指两个枚举项组合的情况,这也是位标志枚举特色,不了解位标志枚举的可以自行先补充一下相关知识点。

具体代码如下:

csharp 复制代码
[Fact]
public void ToEnumByName()
{
    //正常枚举名称字符串,成功转换成枚举
    var status = "Standby".ToEnumByName<StatusEnum>();
    Assert.Equal(StatusEnum.Standby, status);
    //不存在的枚举名称字符串,返回空
    var isStatusNull = "StandbyNull".ToEnumByName<StatusEnum>();
    Assert.Null(isStatusNull);
    //整数类型的字符串,返回空
    var isStatusNullInt = "3".ToEnumByName<StatusEnum>();
    Assert.Null(isStatusNullInt);
    //正常位标志枚举名称字符串,成功转换成枚举
    var flags = "HttpAndUdp".ToEnumByName<TypeFlagsEnum>();
    Assert.Equal(TypeFlagsEnum.HttpAndUdp, flags);
    //不存在的位标志枚举名称字符串,返回空
    var isFlagsNull = "HttpAndUdpNull".ToEnumByName<TypeFlagsEnum>();
    Assert.Null(isFlagsNull);
    //正常的位标志枚举名称组合字符串,成功转换成枚举
    var flagsGroup = "Http,Tcp".ToEnumByName<TypeFlagsEnum>();
    Assert.Equal(TypeFlagsEnum.Http | TypeFlagsEnum.Tcp, flagsGroup);
    //不存在的位标志枚举名称组合字符串,返回空
    var isFlagsGroupNull = "Http,Tcp,Null".ToEnumByName<TypeFlagsEnum>();
    Assert.Null(isFlagsGroupNull);
}

02、根据枚举名称转换成枚举或默认值

该方法是对上一个方法的补充,用于处理转换不成功时,则返回一个指定默认枚举值,具体代码如下:

csharp 复制代码
//根据枚举名称转换成枚举,转换失败则返回默认枚举
public static T ToEnumOrDefaultByName<T>(this string name, T defaultValue) where T : struct, Enum
{
    //调用根据枚举名称转换成枚举方法
    var result = name.ToEnumByName<T>();
    if (result.HasValue)
    {
        return result.Value;
    }
    //转换失败则返回默认值
    return defaultValue;
}

因为该方法调用了上一个方法,因此我们就简单测试一下,转换成功返回正确的值,转换失败则返回默认值,具体代码如下:

csharp 复制代码
[Fact]
public void ToEnumOrDefaultByName()
{
    //正常枚举名称字符串,成功转换成枚举
    var status = "Standby".ToEnumOrDefaultByName(StatusEnum.Normal);
    Assert.Equal(StatusEnum.Standby, status);
    //不存在的枚举名称字符串,返回指定默认值
    var statusDefault = "StandbyNull".ToEnumOrDefaultByName(StatusEnum.Standby);
    Assert.Equal(StatusEnum.Standby, statusDefault);
}

03、根据枚举描述转换成枚举

该方法接收枚举描述字符串,并转为对应枚举,转换失败则返回空,其中如果枚举项没有描述则以枚举名称代替,具体代码如下:

csharp 复制代码
//根据枚举描述转换成枚举,转换失败返回空
public static T? ToEnumByDesc<T>(this string description) where T : struct, Enum
{
    //首先获取枚举所有项
    foreach (Enum value in Enum.GetValues(typeof(T)))
    {
        //取枚举项描述与目标描述相比较,相同则返回该枚举项
        if (value.ToEnumDesc() == description)
        {
            return (T)value;
        }
    }
    //未查到匹配描述则返回默认值
    return default;
}

其中ToEnumDesc方法下文会详细讲解。

我们针对该方法进行以下五种情况进行单元测试:

(1) 正常枚举描述字符串,成功转换成枚举;

(2) 如果枚举项没有枚举描述,则枚举名称字符串,成功转换成枚举;

(3) 不存在的枚举描述字符串,返回空;

(4) 正常位标志枚举描述字符串,成功转换成枚举;

(5) 不存在的位标志枚举描述字符串转换,返回空;

具体代码如下:

csharp 复制代码
[Fact]
public void ToEnumByDescription()
{
    //正常枚举描述字符串,成功转换成枚举
    var status = "待机".ToEnumByDesc<StatusEnum>();
    Assert.Equal(StatusEnum.Standby, status);
    //如果枚举项没有枚举描述,则枚举名称字符串,成功转换成枚举
    var statusNotDesc = "Online".ToEnumByDesc<StatusEnum>();
    Assert.Equal(StatusEnum.Online, statusNotDesc);
    //不存在的枚举描述字符串,返回空
    var isStatusNull = "待机无".ToEnumByDesc<StatusEnum>();
    Assert.Null(isStatusNull);
    //正常位标志枚举描述字符串,成功转换成枚举
    var flags = "Http协议,Udp协议".ToEnumByDesc<TypeFlagsEnum>();
    Assert.Equal(TypeFlagsEnum.HttpAndUdp, flags);
    //不存在的位标志枚举描述字符串转换,返回空
    var isFlagsNull = "Http协议Udp协议".ToEnumByDesc<TypeFlagsEnum>();
    Assert.Null(isFlagsNull);
}

04、根据枚举描述转换成枚举或默认值

该方法是对上一个方法的补充,用于处理转换不成功时,则返回一个指定默认枚举值,其中如果枚举项没有描述则以枚举名称代替,具体代码如下:

csharp 复制代码
//根据枚举描述转换成枚举,转换失败返回默认枚举
public static T? ToEnumOrDefaultByDesc<T>(this string description, T defaultValue) where T : struct, Enum
{
    //调用根据枚举描述转换成枚举方法
    var result = description.ToEnumByDesc<T>();
    if (result.HasValue)
    {
        return result.Value;
    }
    //未查到匹配描述则返回默认值
    return defaultValue;
}

同样的我们进行简单的单元测试:

csharp 复制代码
[Fact]
public void ToEnumOrDefaultByDesc()
{
    //正常枚举描述字符串,成功转换成枚举
    var status = "待机".ToEnumOrDefaultByDesc(StatusEnum.Offline);
    Assert.Equal(StatusEnum.Standby, status);
    //不存在的枚举描述字符串,返回指定默认值
    var statusDefault = "待机无".ToEnumOrDefaultByDesc(StatusEnum.Offline);
    Assert.Equal(StatusEnum.Offline, statusDefault);
}

05、根据枚举名称转换成枚举值

该方法接收枚举名字字符串,并转为对应枚举值,转换失败则返回空,具体代码如下:

csharp 复制代码
//根据枚举名称转换成枚举值,转换失败则返回空
public static int? ToEnumValueByName<T>(this string name) where T : struct, Enum
{
    //调用根据枚举名称转换成枚举方法
    var result = name.ToEnumByName<T>();
    if (result.HasValue)
    {
        return Convert.ToInt32(result.Value);
    }
    //转换失败则返回空
    return default;
}

我们对其进行以下五种情况做详细的单元测试:

(1) 正常枚举名称字符串,成功转换成枚举值;

(2) 不存在的枚举名称字符串,返回空;

(3) 正常位标志枚举名称字符串,成功转换成枚举值;

(4) 正常的位标志枚举名称组合字符串,成功转换成枚举值;

(5) 不存在的位标志枚举Int值转换则返回空;

具体代码如下:

csharp 复制代码
[Fact]
public void ToEnumValueByName()
{
    //正常枚举名称字符串,成功转换成枚举值
    var status = "Standby".ToEnumValueByName<StatusEnum>();
    Assert.Equal(1, status);
    //不存在的枚举名称字符串,返回空
    var isStatusNull = "StandbyNull".ToEnumValueByName<StatusEnum>();
    Assert.Null(isStatusNull);
    //正常位标志枚举名称字符串,成功转换成枚举值
    var flags = "HttpAndUdp".ToEnumValueByName<TypeFlagsEnum>();
    Assert.Equal(3, flags);
    //正常的位标志枚举名称组合字符串,成功转换成枚举值
    var flagsGroup = "Http,Udp".ToEnumValueByName<TypeFlagsEnum>();
    Assert.Equal(3, flagsGroup);
    //不存在的位标志枚举名称字符串,返回空
    var isFlagsNull = "HttpUdp".ToEnumValueByName<TypeFlagsEnum>();
    Assert.Null(isFlagsNull);
}

06、根据枚举名称转换成枚举值或默认值

该方法是对上一个方法的补充,用于处理转换不成功时,则返回一个指定默认枚举值,具体代码如下:

csharp 复制代码
//根据枚举名称转换成枚举值,转换失败则返回默认枚举值
public static int ToEnumValueOrDefaultByName<T>(this string name, int defaultValue) where T : struct, Enum
{
    //根据枚举名称转换成枚举值
    var result = name.ToEnumValueByName<T>();
    if (result.HasValue)
    {
        return result.Value;
    }
    //转换失败则返回默认值
    return defaultValue;
}

我们进行简单的单元测试,具体代码如下:

csharp 复制代码
[Fact]
public void ToEnumValueOrDefaultByName()
{
    //正常枚举名称字符串,成功转换成枚举值
    var status = "Standby".ToEnumValueOrDefaultByName<StatusEnum>(2);
    Assert.Equal(1, status);
    //不存在的枚举名称字符串,返回指定默认值
    var statusDefault = "StandbyNull".ToEnumValueOrDefaultByName<StatusEnum>(2);
    Assert.Equal(2, statusDefault);
}

07、根据枚举名称转换成枚举描述

该方法接收枚举名字字符串,并转为对应枚举描述,转换失败则返回空,其中如果枚举项没有描述则以枚举名称代替,具体代码如下:

csharp 复制代码
//根据枚举名称转换成枚举描述,转换失败则返回空
public static string? ToEnumDescByName<T>(this string name) where T : struct, Enum
{
    //调用根据枚举名称转换成枚举方法
    var result = name.ToEnumByName<T>();
    if (result.HasValue)
    {
        //转为枚举描述
        return result.Value.ToEnumDesc();
    }
    //转换失败则返回空
    return default;
}

因为该方法内部都是调用现有方法,因此做个简单单元测试,具体代码如下:

csharp 复制代码
[Fact]
public void ToEnumDescByName()
{
    //正常位标志枚举名称字符串,成功转换成枚举描述
    var flags = "HttpAndUdp".ToEnumDescByName<TypeFlagsEnum>();
    Assert.Equal("Http协议,Udp协议", flags);
    //正常的位标志枚举名称组合字符串,组合项存在,成功转换成枚举描述
    var flagsGroup = "Http,Udp".ToEnumDescByName<TypeFlagsEnum>();
    Assert.Equal("Http协议,Udp协议", flagsGroup);
    //正常的位标志枚举名称组合字符串,组合项不存在,成功转换成枚举描述
    var flagsGroup1 = "Http,Tcp".ToEnumDescByName<TypeFlagsEnum>();
    Assert.Equal("Http协议,Tcp协议", flagsGroup1);
}

08、根据枚举名称转换成枚举描述或默认值

该方法是对上一个方法的补充,用于处理转换不成功时,则返回一个指定默认枚举描述,具体代码如下:

csharp 复制代码
//根据枚举名称转换成枚举描述,转换失败则返回默认枚举描述
public static string ToEnumDescOrDefaultByName<T>(this string name, string defaultValue) where T : struct, Enum
{
    //调用根据枚举名称转换成枚举描述方法
    var result = name.ToEnumDescByName<T>();
    if (!string.IsNullOrWhiteSpace(result))
    {
        return result;
    }
    //转换失败则返回默认枚举描述
    return defaultValue;
}

做个简单单元测试,具体代码如下:

csharp 复制代码
[Fact]
public void ToEnumDescOrDefaultByName()
{
    //正常枚举名称字符串,成功转换成枚举描述
    var status = "Standby".ToEnumDescOrDefaultByName<StatusEnum>("测试");
    Assert.Equal("待机", status);
    //不存在的枚举名称字符串,返回指定默认枚举描述
    var statusDefault = "StandbyNull".ToEnumDescOrDefaultByName<StatusEnum>("测试");
    Assert.Equal("测试", statusDefault);
}

稍晚些时候我会把库上传至Nuget,大家可以直接使用Ideal.Core.Common。

:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Ideal

相关推荐
wyh要好好学习28 分钟前
C# WPF 记录DataGrid的表头顺序,下次打开界面时应用到表格中
开发语言·c#·wpf
AitTech29 分钟前
C#实现:电脑系统信息的全面获取与监控
开发语言·c#
shitian08111 小时前
用轻量云服务器搭建一个开源的商城系统,含小程序和pc端
服务器·小程序·开源
咩咩觉主1 小时前
尽量通俗易懂地概述.Net && U nity跨语言/跨平台相关知识
unity·c#·.net·.netcore
yngsqq1 小时前
035集——BOUNDARY获取图形外轮廓(CAD—C#二次开发入门)
开发语言·javascript·c#
墨笺染尘缘2 小时前
Unity——对RectTransform进行操作
ui·unity·c#·游戏引擎
修复bug2 小时前
npm完整发包流程(亲测可验证)
前端·npm·开源
IT规划师10 小时前
开源 - Ideal库 - 常用枚举扩展方法(二)
开源·c#·.net core·ideal库·枚举转换
_xaboy11 小时前
开源项目低代码表单设计器FcDesigner扩展组件分组
低代码·开源·动态表单·formcreate·低代码表单·可视化表单设计器