宝哥软件园

ASP .净核心中使用枚举类而不是枚举的方法

编辑:宝哥软件园 来源:互联网 时间:2021-08-23

前言:

我相信大家在编写代码时经常会遇到各种状态值,而且为了避免硬编码和代码中出现魔法数,通常我们都会定义一个枚举,来表示各种状态值,直到我看到爪哇中这样使用枚举,我再想C#中可不可以这样写,今天就分享一下我的感悟。

一、通常我们是这样使用枚举的

(1)开关中使用枚举

公共枚举员工类型{经理、服务人员、地区助理经理}公共类employee Type { public employee Type { get;设置;}公共十进制奖金{获取设置;} }静态无效流程奖金(员工员工){开关(员工类型){ case EmployeeType .经理:员工。奖金=1000米;打破;案例员工类型.Servant:员工。奖金=0.01米;打破;案例员工类型.助理区域经理:员工。奖金=1.0m打破;默认值:抛出新的argumentoutofrangerexception();} }在没有进某唐时我也是这样的写的,代码很烂,违法了开闭原则,扩展性极差。在代码规范中是不允许出现这样的写法的。对于上面的写法可以使用设计模式来重构。后面会继续更新设计模式的文章。

(2)类型转换

EnumTricks .IsVolumeHigh((卷)27);EnumTricks .高((整数)中);二、枚举的不好之处

关于枚举的微软官方文档说了什么:

“枚举关键字用于声明枚举,这是一种独特的类型,由一组名为枚举列表的命名常量组成。每个枚举类型都有一个基础类型,它可以是除茶之外的任何整数类型。枚举元素的默认基础类型是int .默认情况下,第一个枚举数的值为0,每个后续枚举数的值都增加1。

(1)没有类型安全

枚举是简单的值类型,可以提供对无效值的保护,并且不会出现任何行为。他们是有用的,因为他们是魔法数字的改进,但就是这样。如果要约束类型可能的值,枚举不一定能帮助您,因为仍然可以提供无效类型。例如,此枚举有三个值,默认情况下将具有(同国际组织)国际组织类型。值范围为一到3。

公共枚举卷{低=1,中,高}公共静态类EnumTricks { public static bool is volumehigh(Volume Volume){ var result=false;开关(音量){大小写音量低:控制台。写线('音量低');打破;案例卷Medium:控制台。写线('卷中等');打破;案例卷高:控制台。写线('音量高');结果=真;打破;}返回结果;} }静态void Main(string[]args){ EnumTricks .IsVolumeHigh((卷)27);控制台ReadKey();}公共静态类EnumTricks {公共静态bool IsVolumeHigh(Volume Volume){ var结果=false开关(音量){大小写音量低:控制台。写线('音量低');打破;案例卷Medium:控制台。写线('卷中等');打破;案例卷高:控制台。写线('音量高');结果=真;打破;}返回结果;}公共静态int EnumToInt(体积体积){ return(int)体积;}公共静态Volume int tonum(int int值){ return(Volume)int值;}公共静态卷字符串类型(字符串字符串值){返回(体积)枚举。解析(类型(卷),字符串值);} public static int string point(字符串字符串值){ var volume=string toneum(字符串值);返回EnumToInt(卷);}公共静态字符串枚举字符串(音量){返回音量.ToString();} }这应该失败,至少在运行时。它没有。这真的很奇怪.在编译期间或运行期间都不会检测到错误的调用。你会觉得自己处于一个虚假的安全状态。如果,我们把传进去的枚举转换为线时,来看看这两种情况有什么不同:

不知道大家在使用枚举的时候有没有有意识的检查传入的值是否有效。枚举。IsDefined()可用于检查int值是否为有效值

解决方案:如果int值在枚举值的定义范围内,则使用Enum。IsDefined()找到它。如果在范围内,则为真;否则为假。

(2)转化

您是否尝试过将枚举转换为int、int转换为enum、string转换为enum以及string转换为enum的int值?以下代码:

公共静态类EnumTricks {公共静态bool IsVolumeHigh(Volume Volume){ var result=false;开关(音量){大小写音量。Low:控制台。写线('音量低');打破;案例卷。Medium:控制台。写线('卷中等');打破;案例卷。High:控制台。写线('音量高');结果=真;打破;}返回结果;}公共静态int EnumToInt(Volume Volume){ return(int)Volume;}公共静态Volume int tonum(int int value){ return(Volume)int value;}公共静态Volume StringToEnum(字符串stringValue) { return (Volume)枚举。解析(类型(卷),字符串值);} public static int string point(string string value){ var volume=string toneum(string value);返回EnumToInt(卷);}}我们日常代码中有这样的类型转换代码吗?还不错,只是类型转换有性能损失。如果我们能改变方式,避免上述问题,这样我们的代码就能更好地维护和扩展,不是更好吗?接下来,我们将通过枚举类来解决这个问题。

第三,使用枚举类代替枚举类型

公共类枚举: IComparable { private readonly int _ value;私有只读字符串_显示名称受保护枚举(){ }受保护枚举(int值,字符串显示名称){ _ value=value_显示名称=显示名称;} public int Value { get { return _ Value;} }公共字符串显示名称{ get { return _ display name} }公共重写字符串ToString(){返回显示名称;} public static IEnumerablet GetAllT(),其中T :枚举,new(){ var type=type of(T);定义变量字段=类型GetFields(BindingFlags .公共|绑定标签.静态|绑定标签. DeclaredOnly);foreach(字段中的定义变量信息){ var instance=new T();var locatedValue=info .GetValue(实例)为t;if (locatedValue!=null){ yield return located值;} } }公共重写bool Equals(对象obj){ var other value=obj as Enumeration;if(其他值==null){ return false;} var typeMatches=GetType().等于. GetType());var valueMatches=_value .等于(其他值。价值);返回类型匹配值匹配;} public override int GetHashCode(){ return _ value .GetHashCode();}公共静态int绝对差(枚举第一个值,枚举第二个值){ var绝对值差异=数学.Abs(第一个值价值-秒价值.价值);返回绝对差异;}公共静态t从值t(整数值)其中T :枚举,new() { var matchingItem=parseT,int(值,' value ',item=item .value==value);返回matchingItem}公共静态T FromDisplayNameT(字符串显示名称)其中T :枚举,new() { var matchingItem=parseT,string(displayName,' displayName ',item=item .显示名称==显示名称);返回matchingItem}私有静态解析器值,字符串描述,FuncT,bool谓词)其中T :枚举,new() { var matchingItem=GetAllT().FirstOrDefault(谓词);if(MatchingItem==null){ var message=string .格式("{0}"在{2}"、值、描述、类型(吨)中不是有效的{ 1 };引发新的应用程序异常(消息);}返回matchingItem } public int compare to(对象其他){ 0返回值比较(((枚举)其他)。价值);} }公共类卷:枚举{私有卷(){引发新异常("");}私有卷(int值,字符串displayName): base(值,displayName) { }公共静态只读卷低=新卷(1,名称为(低)).tolowerinvality());公共静态只读卷介质=新卷(2,名为(介质))。tolowerinvality());公共静态只读卷高=新卷(3,名为(高))。tolowerinvality());公共静态IEnumerabLevolume List()=new[]{ 0低、中、高};公共静态卷自(整数值){变量状态=列表()。单个默认值(s=s . Value==Value);if(state==null){ 0引发新异常($ '卷: { String }的可能值。联接(',',列表()。选择(s=s . Value))} ');}返回状态;}公共静态卷FromName(字符串名称){ var state=List().SingleOrDefault(s=String).等于。显示名称,名称,字符串比较CurrentCultureIgnoreCase));if(state==null){ 0引发新异常($ '卷: { String }的可能值。联接(',',列表()。选择(s=s .显示名称))} ');}返回状态;} }静态void Main(string[]args){//EnumTricks .IsVolumeHigh((卷)27);//var tmp=Enum .已定义(类型(卷),3);//var str=EnumTricks .枚举字符串((卷)27);//var str2=EnumTricks .枚举字符串((卷)3);//控制台WriteLine($“Volume 27: { str }”);//控制台WriteLine($“Volume 3: { str 2 }”);控制台写入行('-');控制台。写线(卷。高。值);控制台。写线(卷很高。显示名称);变化体积=体积。从(2);变量体积2=体积从名字开始(' high ');变量无=体积。从(27);控制台ReadKey();}四、应用

代码如下:

错误文件下:

公共接口icomonerror { int GetErrCode();字符串GetErrMsg();ICommonError SetErrMsg(字符串errMsg);} public class Enumeration : IComparable { private readonly int _ value;私有只读字符串_显示名称受保护枚举(){ }受保护枚举(int值,字符串显示名称){ _ value=value_显示名称=显示名称;} public int Value { get { return _ Value;} }公共字符串显示名称{ get { return _ display name} }公共重写字符串ToString(){返回显示名称;} public static IEnumerablet GetAllT(),其中T :枚举,new(){ var type=type of(T);定义变量字段=类型GetFields(BindingFlags .公共|绑定标签.静态|绑定标签. DeclaredOnly);foreach(字段中的定义变量信息){ var instance=new T();var locatedValue=info .GetValue(实例)为t;if (locatedValue!=null){ yield return located值;} } }公共重写bool Equals(对象obj){ var other value=obj as Enumeration;if(其他值==null){ return false;} var typeMatches=GetType().等于. GetType());var valueMatches=_value .等于(其他值。价值);返回类型匹配值匹配;} public override int GetHashCode(){ return _ value .GetHashCode();}公共静态int绝对差(枚举第一个值,枚举第二个值){ var绝对值差异=数学.Abs(第一个值价值-秒价值.价值);返回绝对差异;}公共静态t从值t(整数值)其中T :枚举,new() { var matchingItem=parseT,int(值,' value ',item=item .value==value);返回matchingItem}公共静态T FromDisplayNameT(字符串显示名称)其中T :枚举,new() { var matchingItem=parseT,string(displayName,' displayName ',item=item .显示名称==显示名称);返回matchingItem}私有静态解析器值,字符串描述,FuncT,bool谓词)其中T :枚举,new() { var matchingItem=GetAllT().FirstOrDefault(谓词);if(MatchingItem==null){ var message=string .格式("{0}"在{2}"、值、描述、类型(吨)中不是有效的{ 1 };引发新的应用程序异常(消息);}返回matchingItem } public int compare to(对象其他){ 0返回值比较(((枚举)其他)。价值);} }公共类EmBusinessError :枚举,ICommonError { private int errCode私有字符串错误信息公共静态只读Embusinesserror参数验证错误=新Embusinesserror(10001,)参数不合法');private Embusineserror(){ 0引发新的异常('私有构造函数不能调用');} private embbusinesrror(int值,字符串显示名称): base(值,显示名称){ this。errcode=值;this . errmsg=display name } public int GetErrCode(){返回此。errcode}公共字符串GetErrMsg(){返回这个。errmsg} public void SetErrCode(int errCode){ this。errCode=errCode} public ICommonError SetErrMsg(字符串errMsg){这个。errMsg=errMsg归还这个;} }//包装器业务异常类实现公共类业务异常:异常,ICommonError {私有常见错误常见错误/直接接收embbusinesserror的传参用于构造业务异常公共业务异常(icomonerror公社rror): base(){ this。公社罗=公社罗;}公共业务异常(icomonerror公社rror,string errMsg): base(){ this。公社罗=公社罗;这个。常见错误。seterrmsg(errMsg);} public int GetErrCode(){返回此。通信错误。GetErrCode();}公共字符串GetErmsg(){返回这个。平民百姓。GetErmsg();} public ICommonError SetErrMsg(字符串errMsg){这个。平民百姓。SetErrMsg(errMsg);归还这个;} public ICommonError GetCommonError(){ return commonError;} }异常中间件:

公共类异常handler middleware { private readonly request delegate next;///summary/////summary////param name=' next '/param public ExceptionHandlerMiddleWare(请求委托next){ this。next=next}公共异步任务调用(HttpContext上下文){尝试{等待下一个(上下文);} catch(Exception ex){ await handleexceptionsync(context,ex);} }私有静态异步任务句柄异常同步(HttpContext上下文,异常异常){ if(异常==null)返回;等待写异常同步(上下文,异常)。配置等待(假);}私有静态异步任务writeexceptionsync(HttpContext上下文,异常异常){ var response=context .回应;回应content TYPe=' application/JSON;charset=utf-8 ';定义变量结果=new CommonReturnType();如果(异常为业务异常){ var业务异常=(业务异常)异常;var err模型=新{ err代码=业务异常.GetErrCode(),errMsg=businessException .GetErrMsg()};结果=CommonReturnType .创建(errModel,‘fail’);}等待回应WriteAsync(JsonConvert .SerializeObject(新{数据=结果GetData(),状态=结果. GetStatus() }).配置等待(假);} }响应文件夹:

公共类CommonReturnType { //表明对应请求的返回处理结果"成功"或"失败"私有字符串状态;//若状态=成功,则数据内返回前端需要的数据数据//若状态=失败,则数据内使用通用的错误码格式私有对象数据;//定义一个通用的创建方法公共静态CommonReturnType创建(对象结果){返回CommonReturnType .创造(结果,'成功');}公共静态CommonReturnType创建(对象结果,字符串状态){ CommonReturnType类型=new CommonReturnType();打字设置状态(状态);打字SetData(结果);返回类型;}公共字符串GetStatus(){返回状态;} public void SetStatus(字符串状态){ this.status=status}公共对象GetData(){ 0返回数据;} public void SetData(对象数据){ this.data=data} }最后推荐一个类库,这是我在框架上发现的枚举类库,地址:https://github。com/arda lis/SmartEnum

好了,先分享到这里,希望对你有帮助和启发。

参考资料:

(1)https://份文件。微软。com/zh-cn/dotnet/standard/微服务-架构/微服务-DDD-cqrs-模式/枚举-类-枚举-类型

(2)https://ardalis。com/enum-alternatives-in-c

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

更多资讯
游戏推荐
更多+