新建一個 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] 附加的特性,也不想額外的增添更多的行爲和特徵時,咱們依然能夠採用最原始的、大衆化的版本。