[C#] 使用 Enum 避免 Magic Number

Magic Number

所谓的 Magic Number 中文翻译是 「魔术数字」,
是指由程式设计者自己定义的某些数字,
旁人不透过注解无法了解其中的涵义,
甚至作者本人在经过一段时间后,自己也会忘了当初这个数字的用途。

像我以前常写这样的程式码

if (user.Identity != 1){    throw new Exception("没有权限。");}

var sexName = user.Sex == 1 ? "男" : "女";

这样的程式有什么问题?

难以阅读,无法从程式码了解这段程式的用途,如果又没有写注解加上作者离职,那就真没人知道这段程式到底在干嘛。
而且随着专案日渐庞大,类似的魔术数字越来越多,注解可能散落各处,或没有跟着程式更新,这都会造成维护上的困难。

难以修改,需求变动或程式重构时,所有用到的地方都要修改,只要漏改一个地方,就会产生一个新 Bug。

C# 可以使用 Enum 来解决此类问题。

第一个例子,可以新增一个 IdentityEnum,统一管理使用者身分的值,这样程式可读性佳,要改变值也只需改一个地方。

public enum Identity{    //管理者    Admin = 1,    //一般使用者    User = 2,}//需判断的地方if (user.Identity != Identity.Admin){    throw new Exception("没有权限。");}

第二个例子,可以新增一个 SexEnum,然后用 GetSexName 来统一管理输出的中文。

public enum Sex{    //男生    Male = 1,        //女生    Female = 2}public string GetSexName(Sex sex){    if (sex == Sex.Male)    {        return "男";    }    return "女";}//需输出中文的地方var sexName = GetSexName(user.Sex);

第二个例子,在 C# 还可以用 [Description("")] Attribute 来改进。

using System.ComponentModel;public enum Sex{    [Description("男")]    Male = 1,    [Description("女")]    Female = 2}

这样不仅可以当 注解,还可以写一个共用的扩充方法 ToDescription 给所有的 Enum 使用,不用再为每个 Enum 写各自的转换函数。

public static class EnumExtenstions{    public static string ToDescription(this Enum value)    {        return value.GetType()            .GetRuntimeField(value.ToString())            .GetCustomAttributes<System.ComponentModel.DescriptionAttribute>()            .FirstOrDefault()?.Description ?? string.Empty;    }}

用法:

var sexName = user.Sex.ToDescription();

Enum 的规则

不指定 Enum 的值,预设由 0 开始排。

public enum Example{    A,     //0    B,     //1    C      //2}

指定其中一项的值,后面的项目会依序递增。

public enum Example{    A = 5,   //5    B,       //6    C        //7}

要注意这种情形,会造成奇怪的结果,但程式不会出错。

public enum Example{    A = -1,     //-1    B = -2,     //-2    C           //-1}

Enum 常见的几种转换

var _enum = Sex.Male;var _number = 1;var _string = "Male";//将 enum 转换为 numbervar val1 = (int)_enum;//将 number 转换为 enumvar val2 = (Sex)_number;//将 enum 转换为 stringvar val3 = _enum.ToString();//将 string 转换为 enumvar val4 = (Sex)Enum.Parse(typeof(Sex), _string);//将 enum 转换为 JSONvar obj = new{    abc = ABC.A};var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);//{"abc":1}

指定 Enum 的数值型态

可以指定的型态有
bytesbyteshortushortintuintlongulong

public enum Sex : byte{    Male,    Female}

Enum 旗标的应用

在 Enum 加上 [Flags] Attribute。

[Flags]public enum ABC{    A = 0x01,    B = 0x02,    C = 0x04}
var abc = ABC.A | ABC.C;var _number = (int)abc;         //5var _string = abc.ToString();   //A, C

结语:
在实务上最常看到 Magic Number 的地方就在资料库,
所以现在我会把这种用数字代表状态的栏位,都做出对应的 Enum 统一管理,
忘记的时候也不用到处找注解或重新阅读程式,只要去那里查一下马上就知道其意义,善用 Enum 真的是最简单提升程式码品质的方式。

参考文章:
魔术数字 (程式设计)
Don't use Magic number in your code
CODE-enum, string, int间的转换
Method that returns description attribute of enum value


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章