新建一个 AlgorithmType 枚举,里面包含 MD五、SHA1 和 SHA2 等一系列的枚举值,默认为 int 类型。有的时候咱们会在对应的枚举值上使用特性 [Description] 来添加备注信息,方便咱们后期提供描述信息(如返回给前端界面展现时可能须要使用)。前端
AlgorithmType.cs程序员
/// <summary> /// 算法类型 /// </summary> public enum AlgorithmType { /// <summary> /// MD5 /// </summary> [Description("Message-Digest Algorithm 5")] MD5, /// <summary> /// SHA1 /// </summary> [Description("Secure Hash Algorithm 1")] SHA1, /// <summary> /// SHA224 /// </summary> [Description("Secure Hash Algorithm 224")] SHA224, /// <summary> /// SHA256 /// </summary> [Description("Secure Hash Algorithm 256")] SHA256, /// <summary> /// SHA384 /// </summary> [Description("Secure Hash Algorithm 384")] SHA384, /// <summary> /// SHA512 /// </summary> [Description("Secure Hash Algorithm 512")] SHA512 }
常见的一个作法是,编写一个扩展方法来获取 enum 的描述信息:算法
public static class EnumExtensionMethods { /// <summary> /// 获取枚举类型的描述信息 /// </summary> public static string GetDescription(this Enum value) { var type = value.GetType(); var name = Enum.GetName(type, value); if (name == null) return null; var field = type.GetField(name); if (!(Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute)) { return name; } return attribute.Description; } }
由于直接输出枚举值,或者经过枚举类型对应的 ToString() 的方式输出字符串,结果都为它自己的文本值,BCL 也并无提供快捷的方式去获取描述信息,因此只能经过相似上述的扩展方法来获取 [DescriptionAttribute]。ide
【分析】由于枚举属于值类型,它不须要在堆上分配空间,而且在计算时(如比较运算)效率相比引用类型更高,因此从性能上枚举类型是占据了绝对的优点;可是因为 BCL 并无提供快捷方式的去获取 [Description],而且编写对应的获取方法也较为麻烦(其实也不麻烦,由于你会使用程序员的两大法宝:CTRL+C 和 CTRL+V)。函数
此次咱们不直接使用 enum,而是采起新建 class 的方式去模仿 enum 类型,也就是使用引用类型来取代值类型,不过,性能方面会有所损耗。性能
HashAlgorithmType.csthis
/// <summary> /// 哈希算法类型 /// </summary> public class HashAlgorithmType { /// <summary> /// MD5 /// </summary> public static readonly HashAlgorithmType MD5 = new HashAlgorithmType(0); /// <summary> /// SHA1 /// </summary> public static readonly HashAlgorithmType SHA1 = new HashAlgorithmType(1); /// <summary> /// SHA224 /// </summary> public static readonly HashAlgorithmType SHA224 = new HashAlgorithmType(2); /// <summary> /// SHA256 /// </summary> public static readonly HashAlgorithmType SHA256 = new HashAlgorithmType(3); /// <summary> /// SHA384 /// </summary> public static readonly HashAlgorithmType SHA384 = new HashAlgorithmType(4); /// <summary> /// SHA512 /// </summary> public static readonly HashAlgorithmType SHA512 = new HashAlgorithmType(5); private readonly int _hashAlgorithmType; private HashAlgorithmType(int hashAlgorithmType) { _hashAlgorithmType = hashAlgorithmType; } public override string ToString() { string result; switch (_hashAlgorithmType) { case 0: result = "Message-Digest Algorithm 5"; break; case 1: result = "Secure Hash Algorithm 1"; break; case 2: result = "Secure Hash Algorithm 224"; break; case 3: result = "Secure Hash Algorithm 256"; break; case 4: result = "Secure Hash Algorithm 384"; break; case 5: result = "Secure Hash Algorithm 512"; break; default: throw new Exception("哈希算法类型有误"); } return result; } }
咱们采用了 private 进行构造函数私有化的操做,这样就不会容许在类的外部 new 对象了;其次,使用 public static readonly 字段提供给外部进行访问,这样的话就和枚举类型的调用方式一致;最后,咱们对 ToString() 方法进行了重写,在 return 的值中返回对应的描述信息。spa
这样,咱们就能够直接经过 class.field 的方式获得对应枚举值的描述信息。code
【分析】性能受损;但 ToString() 比 GetDescription() 更浅显直白、清晰明了;不过,参数以数字“写死”的方式进行提供也欠妥。对象
在上一个版本的类中,咱们在进行构造函数初始化时直接使用了数字 0~5,而且重写 ToString() 时也是直接使用数字 0~5,除了不直观的因素以外,随着枚举值数量的增长,枚举值和自身描述二者间的对应关系也容易出错。如今,咱们尝试以私有嵌套类的形式将 enum 和 class 的二者有机结合起来。
HashAlgorithmType.cs
/// <summary> /// 哈希算法类型 /// </summary> public class HashAlgorithmType { /// <summary> /// MD5 /// </summary> public static HashAlgorithmType MD5 = new HashAlgorithmType(AlgorithmType.MD5); /// <summary> /// SHA1 /// </summary> public static readonly HashAlgorithmType SHA1 = new HashAlgorithmType(AlgorithmType.SHA1); /// <summary> /// SHA224 /// </summary> public static readonly HashAlgorithmType SHA224 = new HashAlgorithmType(AlgorithmType.SHA224); /// <summary> /// SHA256 /// </summary> public static readonly HashAlgorithmType SHA256 = new HashAlgorithmType(AlgorithmType.SHA256); /// <summary> /// SHA384 /// </summary> public static readonly HashAlgorithmType SHA384 = new HashAlgorithmType(AlgorithmType.SHA384); /// <summary> /// SHA512 /// </summary> public static readonly HashAlgorithmType SHA512 = new HashAlgorithmType(AlgorithmType.SHA512); /// <summary> /// 算法类型 /// </summary> private readonly AlgorithmType _algorithmType; private HashAlgorithmType(AlgorithmType algorithmType) { _algorithmType = algorithmType; } public override string ToString() { string result; switch (_algorithmType) { case AlgorithmType.MD5: result = "Message-Digest Algorithm 5"; break; case AlgorithmType.SHA1: result = "Secure Hash Algorithm 1"; break; case AlgorithmType.SHA224: result = "Secure Hash Algorithm 224"; break; case AlgorithmType.SHA256: result = "Secure Hash Algorithm 256"; break; case AlgorithmType.SHA384: result = "Secure Hash Algorithm 384"; break; case AlgorithmType.SHA512: result = "Secure Hash Algorithm 512"; break; default: throw new Exception("哈希算法类型有误"); } return result; } /// <summary> /// 算法类型 /// </summary> private enum AlgorithmType { /// <summary> /// MD5 /// </summary> MD5, /// <summary> /// SHA1 /// </summary> SHA1, /// <summary> /// SHA224 /// </summary> SHA224, /// <summary> /// SHA256 /// </summary> SHA256, /// <summary> /// SHA384 /// </summary> SHA384, /// <summary> /// SHA512 /// </summary> SHA512 } }
在 HashAlgorithmType 类中,新建了一个私有的 AlgorithmType 枚举,这样就只容许 HashAlgorithmType 类访问,而不会在该类的外部(其它类型)进行访问。
正所谓萝卜青菜,各有所爱,假如你过于关于效率性能,或者说不须要使用诸如 [Description] 附加的特性,也不想额外的增添更多的行为和特征时,咱们依然能够采用最原始的、大众化的版本。