.NET的強類型字符串(Strongly typed string)詳解
在.NET
中,強類型字符串(Strongly typed string)并不是一個官方的概念,是指使用特定的結(jié)構(gòu)來表示某種類型字符串?dāng)?shù)據(jù)的編碼實踐。類似于枚舉,可以提供編譯時檢查類型,減少運行時錯誤,以及更好的可讀性和維護(hù)性。相比于枚舉,具有更好的擴展性以及更強的約束性。
枚舉
枚舉提供了一種便捷的方法來使用相關(guān)常數(shù)集并將常數(shù)值與名稱相關(guān)聯(lián),具有類型安全、可讀性高以及編譯時檢查等優(yōu)點。但是枚舉類型不能定義任何方法、屬性或事件,只能通過擴展方法功能模擬向枚舉類型添加方法。
盡管枚舉提供了編譯時檢查,但對輸入值的約束是有限的。例如,下面這個枚舉有四個值,默認(rèn)情況下是int類型。取值范圍為0 ~ 3。
public enum Roles { Author, Editor, Administrator, SalesRepresentative }
然后,有一個方法接受這個枚舉類型的參數(shù):
public string DoSomething(Roles role) { return role.ToString(); }
許多開發(fā)人員可能不會檢查傳入值是否為實際有效的枚舉值。任何int類型都可以轉(zhuǎn)換,可能出現(xiàn)下邊這種代碼:
var result = myObject.DoSomething((Roles)10);
輸出的結(jié)果是 “10”,如果后續(xù)代碼中有基于這個枚舉的分支語句或者條件判斷,將產(chǎn)生錯誤的結(jié)果。對于這種情況,強類型字符串是一個不錯的選擇。
強類型字符串(Strongly typed string)
強類型字符串要聲明成帶有字符串構(gòu)造函數(shù)的不可變值類型(struct),即要在該類型上用 readonly
修飾符,并為其實現(xiàn) IEquatable<T>
接口。要覆寫強類型字符串的 ToString()
方法,以返回隱式的字符串值。并將已知的強類型字符串通過靜態(tài)只讀屬性聲明到該類型上。
為了讓強類型字符串在通用代碼的語言結(jié)構(gòu)上看起來更像字符串或者枚舉,需要為強類型字符串覆寫相等運算符。
以下就是 .NET
源碼中加密哈希算法的名稱強類型字符串HashAlgorithmName的代碼
using System.Diagnostics.CodeAnalysis; namespace System.Security.Cryptography { public readonly struct HashAlgorithmName : IEquatable<HashAlgorithmName> { public static HashAlgorithmName MD5 { get { return new HashAlgorithmName("MD5"); } } public static HashAlgorithmName SHA1 { get { return new HashAlgorithmName("SHA1"); } } public static HashAlgorithmName SHA256 { get { return new HashAlgorithmName("SHA256"); } } public static HashAlgorithmName SHA384 { get { return new HashAlgorithmName("SHA384"); } } public static HashAlgorithmName SHA512 { get { return new HashAlgorithmName("SHA512"); } } public static HashAlgorithmName SHA3_256 => new HashAlgorithmName("SHA3-256"); public static HashAlgorithmName SHA3_384 => new HashAlgorithmName("SHA3-384"); public static HashAlgorithmName SHA3_512 => new HashAlgorithmName("SHA3-512"); private readonly string? _name; public HashAlgorithmName(string? name) { // Note: No validation because we have to deal with default(HashAlgorithmName) regardless. _name = name; } public string? Name { get { return _name; } } public override string ToString() { return _name ?? string.Empty; } public override bool Equals([NotNullWhen(true)] object? obj) { return obj is HashAlgorithmName && Equals((HashAlgorithmName)obj); } public bool Equals(HashAlgorithmName other) { // NOTE: intentionally ordinal and case sensitive, matches CNG. return _name == other._name; } public override int GetHashCode() { return _name == null ? 0 : _name.GetHashCode(); } public static bool operator ==(HashAlgorithmName left, HashAlgorithmName right) { return left.Equals(right); } public static bool operator !=(HashAlgorithmName left, HashAlgorithmName right) { return !(left == right); } //其他擴展功能 public static bool TryFromOid(string oidValue, out HashAlgorithmName value) { ArgumentNullException.ThrowIfNull(oidValue); switch (oidValue) { case Oids.Md5: value = MD5; return true; case Oids.Sha1: value = SHA1; return true; case Oids.Sha256: value = SHA256; return true; case Oids.Sha384: value = SHA384; return true; case Oids.Sha512: value = SHA512; return true; case Oids.Sha3_256: value = SHA3_256; return true; case Oids.Sha3_384: value = SHA3_384; return true; case Oids.Sha3_512: value = SHA3_512; return true; default: value = default; return false; } } public static HashAlgorithmName FromOid(string oidValue) { if (TryFromOid(oidValue, out HashAlgorithmName value)) { return value; } throw new CryptographicException(SR.Format(SR.Cryptography_InvalidHashAlgorithmOid, oidValue)); } } }
這段代碼更好地約束了加密哈希算法名稱的輸入,同時還擴展了其他功能。但比枚舉繁瑣不少。
根據(jù)《框架設(shè)計指南》建議:當(dāng)基類支持一組固定的輸入?yún)?shù),但是派生類需要支持更多的參數(shù)時,建議使用強類型字符串;當(dāng)僅由密封類型使用時,只需要使用預(yù)定義的值,枚舉將是更好的選擇。
此外,枚舉通常定義的是封閉的選項集,對于操作系統(tǒng)版本這種開放集合,也建議使用強類型字符串??丶?nbsp;HandyControl
中的 SystemVersionInfo
正是這樣的例子。
參考資料
Enum Alternatives in C# | Blog
使用枚舉類(而不是枚舉類型) - .NET | Microsoft Learn
到此這篇關(guān)于什么是.NET的強類型字符串(Strongly typed string)的文章就介紹到這了,更多相關(guān).NET強類型字符串內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
.Net core下直接執(zhí)行SQL語句并生成DataTable的實現(xiàn)方法
.net core可以執(zhí)行SQL語句,但是只能生成強類型的返回結(jié)果。這篇文章主要介紹了.Net core下直接執(zhí)行SQL語句并生成DataTable的相關(guān)資料,需要的朋友可以參考下2016-11-11ASP.NET The system cannot find the file specified解決辦法
這篇文章主要介紹了ASP.NET The system cannot find the file specified解決辦法的相關(guān)資料,需要的朋友可以參考下2016-11-11ASP.NET使用HttpWebRequest讀取遠(yuǎn)程網(wǎng)頁源代碼
本文分享了一個使用HttpWebRequest讀取遠(yuǎn)程網(wǎng)頁的案例,供大家參考學(xué)習(xí)。2016-03-03ASP.NET?Core中Razor頁面與MVC區(qū)別介紹
這篇文章介紹了ASP.NET?Core中Razor頁面與MVC的區(qū)別,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02.net?core利用PdfSharpCore操作PDF實例教程
操作pdf是我們?nèi)粘i_發(fā)中經(jīng)常遇到的功能,下面這篇文章主要給大家介紹了關(guān)于.net?core利用PdfSharpCore操作PDF實例的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12.NET微服務(wù)架構(gòu)CI/CD自動構(gòu)建Jenkins+Gitee
這篇文章介紹了.NET使用微服務(wù)架構(gòu)CI/CD自動構(gòu)建Jenkins+Gitee的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01asp.net實現(xiàn)在非MVC中使用Razor模板引擎的方法
這篇文章主要介紹了asp.net實現(xiàn)在非MVC中使用Razor模板引擎的方法,較為詳細(xì)的分析了Razor模板引擎的使用技巧,需要的朋友可以參考下2015-06-06