Magic Number
所谓的 Magic Number 中文翻译是 「魔术数字」,
是指由程式设计者自己定义的某些数字,
旁人不透过注解无法了解其中的涵义,
甚至作者本人在经过一段时间后,自己也会忘了当初这个数字的用途。
像我以前常写这样的程式码
if (user.Identity != 1){ throw new Exception("没有权限。");}
或
var sexName = user.Sex == 1 ? "男" : "女";
这样的程式有什么问题?
难以阅读,无法从程式码了解这段程式的用途,如果又没有写注解加上作者离职,那就真没人知道这段程式到底在干嘛。
而且随着专案日渐庞大,类似的魔术数字越来越多,注解可能散落各处,或没有跟着程式更新,这都会造成维护上的困难。
难以修改,需求变动或程式重构时,所有用到的地方都要修改,只要漏改一个地方,就会产生一个新 Bug。
在 C#
可以使用 Enum
来解决此类问题。
第一个例子,可以新增一个 Identity
的 Enum
,统一管理使用者身分的值,这样程式可读性佳,要改变值也只需改一个地方。
public enum Identity{ //管理者 Admin = 1, //一般使用者 User = 2,}//需判断的地方if (user.Identity != Identity.Admin){ throw new Exception("没有权限。");}
第二个例子,可以新增一个 Sex
的 Enum
,然后用 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 的数值型态
可以指定的型态有byte
、sbyte
、short
、ushort
、int
、uint
、long
、ulong
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