服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - c# 怎样简洁高效的实现多个 Enum 自由转换

c# 怎样简洁高效的实现多个 Enum 自由转换

2022-10-12 13:24一线码农 C#

这篇文章主要介绍了c# 怎样简洁高效的实现多个 Enum 自由转换,帮助大家更好的进行c# 开发,感兴趣的朋友可以了解下

一:背景

1. 讲故事

前段时间和同事负责一个项目的两个业务模块,可能大家缺少沟通,导致本该定义一个 Enum 的地方结果我俩各自定义了一个,导致后面这两个 Enum 进行对接就烦了,为了方便理解,也不想让大家看这崴脚的英文拼写,我就拿 银行 举例吧。

  • A同事 定义的枚举
?
1
2
3
4
5
6
public enum BankEnum
{
  ICBC = 1,
  CMSB = 2,
  CMBC = 3
}
  • B同事 定义的枚举
?
1
2
3
4
5
6
public enum ChinaBankEnum
{
  中国民生银行 = 1,
  中国工商银行 = 2,
  中国招商银行 = 3,
}

这就很尬尴了,怎么将 ChinaBankEnum 转成 BankEnum 呢? 为了寻求多快好省,本篇就聊聊这个问题。

二:寻找解决办法

1. 手工匹配

本质上就是找两个 Enum 的 mapping 关系,人肉匹配那是最简单粗暴的,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
static BankEnum ConvertToEnum(ChinaBankEnum chinaBank)
{
  switch (chinaBank)
  {
    case ChinaBankEnum.中国工商银行: return BankEnum.ICBC;
    case ChinaBankEnum.中国民生银行: return BankEnum.CMSB;
    case ChinaBankEnum.中国招商银行: return BankEnum.CMBC;
  }
 
  return default(BankEnum);
}

看的出来,这种写法缺少灵活性,作为程序员肯定不能满足于此,既然是找 mapping 关系,我相信很多朋友最早听说 mapping 一词是来源于 EntityFramework ,人家在处理 table 到 model 的 mapping 采用的是 Attribute,是不是这样,灵感就在于此,我是不是也可以使用 Attribute 来标记两个 Enum 的对应关系呢???

2. 使用 Attribute

有了这个思路,就可以自定义一个 Attribute,当然比较懒的话,也可以用 Framework 自带的 DescriptionAttribute,代码如下:

?
1
2
3
4
5
6
7
[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
  public DescriptionAttribute(){}
 
  public DescriptionAttribute(string description){}
}

接下来就可以把 Description 套在 BankEnum 上,如下代码所示:

?
1
2
3
4
5
6
7
8
9
10
11
public enum BankEnum
{
  [Description(nameof(ChinaBankEnum.中国工商银行))]
  ICBC = 1,
 
  [Description(nameof(ChinaBankEnum.中国民生银行))]
  CMSB = 2,
 
  [Description(nameof(ChinaBankEnum.中国招商银行))]
  CMBC = 3
}

然后我可以通过反射拿到 Attribute 的值再去 ChinaBankEnum 中去找对应的 key 即可,对不对,为了方便理解,我封装一个 Enum 的扩展方法,通过反射实现 Enum 对 Enum 的转换,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/// <summary>
/// 枚举的扩展方法
/// </summary>
public static class EnumExtension
{
  public static Target ConvertTo<Target>(this Enum enumValue) where Target : Enum
  {
    var key = Enum.GetName(enumValue.GetType(), enumValue);
 
    var fields = typeof(Target).GetFields();
 
    foreach (var field in fields)
    {
      var attribute = field.GetCustomAttribute<DescriptionAttribute>();
 
      if (attribute == null) continue;
 
      if (key == attribute.Description)
      {
        var obj = (Target)field.GetValue(typeof(Target));
        return obj;
      }
    }
 
    return default(Target);
  }
}

代码逻辑还是比较简单的,接下来写两个例子测试下:

?
1
2
3
4
5
6
7
8
9
10
static void Main(string[] args)
{
  ChinaBankEnum chinaBankEnum = ChinaBankEnum.中国工商银行;
  ChinaBankEnum chinaBankEnum2 = ChinaBankEnum.中国招商银行;
 
  var bankEnum = chinaBankEnum.ConvertTo<BankEnum>();
  var bankEnum2 = chinaBankEnum2.ConvertTo<BankEnum>();
 
  Console.WriteLine($"{chinaBankEnum} -> {bankEnum}\r\n{chinaBankEnum2} -> {bankEnum2}");
}

c# 怎样简洁高效的实现多个 Enum 自由转换

3. 对 Parse 转换的一些优化

不知道大家在写代码的时候有没有发现将 string 或者 int 转成 Enum 的时候,写出来的代码是又臭又长,比如下面这样:

?
1
var bankEnum = (ChinaBankEnum)Enum.Parse(typeof(ChinaBankEnum), "中国工商银行");

又是 typeof 又是类型强转换,而且强转不过来的话还会抛异常,基于各种原因 framework 又新增了一个 TryParse,如下图所示:

c# 怎样简洁高效的实现多个 Enum 自由转换

看起来确实好多了,但还是觉得有点不爽,为了再顺眼一些,我决定在 EnumExtension 中再封装一个 TryParse 方法,如下代码所示:

?
1
2
3
4
5
6
7
8
9
10
11
public static class EnumExtension
{
  public static T TryParse<T>(this string value) where T : struct
  {
    var isSucc = Enum.TryParse<T>(value, out var result);
 
    if (!isSucc) return default(T);
 
    return result;
  }
}

调用的时候就可以这么来: var bankEnum = "中国工商银行".TryParse<ChinaBankEnum>();,是不是就顺眼多了哈。

三: 总结

哈,本篇就来自于项目开发中遇到的一个坑,相信很多朋友都会遇到类似的情况,遗憾的是默认的 Enum 提供的功能太弱,大家可以根据自己的业务在 Enum 上扩充更多实用的方法,如获取所有的key,所有的value 等等,让自己的代码更加整洁,干净,强大!

以上就是c# 怎样简洁高效的实现多个 Enum 自由转换的详细内容,更多关于c# Enum 自由转换的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/huangxincheng/p/13850587.html

延伸 · 阅读

精彩推荐
  • C#C# WPF 父控件通过使用可视化树找到子控件的示例代码

    C# WPF 父控件通过使用可视化树找到子控件的示例代码

    这篇文章主要介绍了C# WPF 父控件通过使用可视化树找到子控件的示例代码,需要的朋友可以参考下...

    hello黄先森4482022-02-28
  • C#C#异常处理总结及简单实例

    C#异常处理总结及简单实例

    这篇文章主要介绍了C#异常处理总结及简单实例的相关资料,需要的朋友可以参考下...

    hgmyz8952022-01-07
  • C#C#读取XML的三种实现方式

    C#读取XML的三种实现方式

    XML文件是一种常用的文件格式,本篇文章主要介绍了C#读取XML的三种实现方式,主要是XmlDocument、XmlTextReader、Linq to Xml,有兴趣的可以了解一下。...

    WindyAmy11972021-12-23
  • C#C# 图片格式转换的实例代码

    C# 图片格式转换的实例代码

    这篇文章主要介绍了C# 图片格式转换的实例代码,文中讲解非常详细,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...

    Alan.hsiang4552022-09-29
  • C#C#连接Oracle的方法实例总结

    C#连接Oracle的方法实例总结

    这篇文章主要介绍了C#连接Oracle的方法,结合实例形式总结分析了几种常见的C#连接Oracle数据库的操作技巧与相关注意事项,需要的朋友可以参考下...

    songkexin11542022-01-11
  • C#如何使用C#在PDF文件添加图片印章

    如何使用C#在PDF文件添加图片印章

    文档中添加印章可以起一定的作用,比如,防止文件随意被使用,或者确保文档内容的安全性和权威性。C#添加图片印章其实也有很多实现方法,这里我使...

    C#教程网11292021-12-21
  • C#Unity Shader实现裁切效果

    Unity Shader实现裁切效果

    这篇文章主要为大家详细介绍了Unity Shader实现裁切效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    ZzEeRO7762022-09-06
  • C#C#实现控制摄像头的类

    C#实现控制摄像头的类

    这篇文章主要介绍了C#实现控制摄像头的类,涉及C#操作摄像头的初始化、抓图、录像等功能,具有一定参考借鉴价值,需要的朋友可以参考下...

    我心依旧5212021-10-26