.NET的強(qiáng)類型字符串(Strongly typed string)詳解
在.NET中,強(qiáng)類型字符串(Strongly typed string)并不是一個(gè)官方的概念,是指使用特定的結(jié)構(gòu)來(lái)表示某種類型字符串?dāng)?shù)據(jù)的編碼實(shí)踐。類似于枚舉,可以提供編譯時(shí)檢查類型,減少運(yùn)行時(shí)錯(cuò)誤,以及更好的可讀性和維護(hù)性。相比于枚舉,具有更好的擴(kuò)展性以及更強(qiáng)的約束性。
枚舉
枚舉提供了一種便捷的方法來(lái)使用相關(guān)常數(shù)集并將常數(shù)值與名稱相關(guān)聯(lián),具有類型安全、可讀性高以及編譯時(shí)檢查等優(yōu)點(diǎn)。但是枚舉類型不能定義任何方法、屬性或事件,只能通過(guò)擴(kuò)展方法功能模擬向枚舉類型添加方法。
盡管枚舉提供了編譯時(shí)檢查,但對(duì)輸入值的約束是有限的。例如,下面這個(gè)枚舉有四個(gè)值,默認(rèn)情況下是int類型。取值范圍為0 ~ 3。
public enum Roles {
Author,
Editor,
Administrator,
SalesRepresentative
}然后,有一個(gè)方法接受這個(gè)枚舉類型的參數(shù):
public string DoSomething(Roles role) {
return role.ToString();
}許多開(kāi)發(fā)人員可能不會(huì)檢查傳入值是否為實(shí)際有效的枚舉值。任何int類型都可以轉(zhuǎn)換,可能出現(xiàn)下邊這種代碼:
var result = myObject.DoSomething((Roles)10);
輸出的結(jié)果是 “10”,如果后續(xù)代碼中有基于這個(gè)枚舉的分支語(yǔ)句或者條件判斷,將產(chǎn)生錯(cuò)誤的結(jié)果。對(duì)于這種情況,強(qiáng)類型字符串是一個(gè)不錯(cuò)的選擇。
強(qiáng)類型字符串(Strongly typed string)
強(qiáng)類型字符串要聲明成帶有字符串構(gòu)造函數(shù)的不可變值類型(struct),即要在該類型上用 readonly 修飾符,并為其實(shí)現(xiàn) IEquatable<T> 接口。要覆寫強(qiáng)類型字符串的 ToString() 方法,以返回隱式的字符串值。并將已知的強(qiáng)類型字符串通過(guò)靜態(tài)只讀屬性聲明到該類型上。
為了讓強(qiáng)類型字符串在通用代碼的語(yǔ)言結(jié)構(gòu)上看起來(lái)更像字符串或者枚舉,需要為強(qiáng)類型字符串覆寫相等運(yùn)算符。
以下就是 .NET 源碼中加密哈希算法的名稱強(qiáng)類型字符串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);
}
//其他擴(kuò)展功能
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));
}
}
}這段代碼更好地約束了加密哈希算法名稱的輸入,同時(shí)還擴(kuò)展了其他功能。但比枚舉繁瑣不少。
根據(jù)《框架設(shè)計(jì)指南》建議:當(dāng)基類支持一組固定的輸入?yún)?shù),但是派生類需要支持更多的參數(shù)時(shí),建議使用強(qiáng)類型字符串;當(dāng)僅由密封類型使用時(shí),只需要使用預(yù)定義的值,枚舉將是更好的選擇。
此外,枚舉通常定義的是封閉的選項(xiàng)集,對(duì)于操作系統(tǒng)版本這種開(kāi)放集合,也建議使用強(qiáng)類型字符串??丶?kù) HandyControl 中的 SystemVersionInfo正是這樣的例子。
參考資料
Enum Alternatives in C# | Blog
使用枚舉類(而不是枚舉類型) - .NET | Microsoft Learn
到此這篇關(guān)于什么是.NET的強(qiáng)類型字符串(Strongly typed string)的文章就介紹到這了,更多相關(guān).NET強(qiáng)類型字符串內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
.Net core下直接執(zhí)行SQL語(yǔ)句并生成DataTable的實(shí)現(xiàn)方法
.net core可以執(zhí)行SQL語(yǔ)句,但是只能生成強(qiáng)類型的返回結(jié)果。這篇文章主要介紹了.Net core下直接執(zhí)行SQL語(yǔ)句并生成DataTable的相關(guān)資料,需要的朋友可以參考下2016-11-11
ASP.NET The system cannot find the file specified解決辦法
這篇文章主要介紹了ASP.NET The system cannot find the file specified解決辦法的相關(guān)資料,需要的朋友可以參考下2016-11-11
ASP.NET使用HttpWebRequest讀取遠(yuǎn)程網(wǎng)頁(yè)源代碼
本文分享了一個(gè)使用HttpWebRequest讀取遠(yuǎn)程網(wǎng)頁(yè)的案例,供大家參考學(xué)習(xí)。2016-03-03
ASP.NET?Core中Razor頁(yè)面與MVC區(qū)別介紹
這篇文章介紹了ASP.NET?Core中Razor頁(yè)面與MVC的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-02-02
.net?core利用PdfSharpCore操作PDF實(shí)例教程
操作pdf是我們?nèi)粘i_(kāi)發(fā)中經(jīng)常遇到的功能,下面這篇文章主要給大家介紹了關(guān)于.net?core利用PdfSharpCore操作PDF實(shí)例的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
DAM 簡(jiǎn)單跨數(shù)據(jù)庫(kù)ADO.NET組件
這是一個(gè)可以實(shí)現(xiàn)簡(jiǎn)單跨數(shù)據(jù)庫(kù)基于ADO.NET的組件。您可以在DAL層透過(guò)它來(lái)訪問(wèn)數(shù)據(jù)庫(kù)。這是一個(gè)以前寫過(guò)一個(gè)小組件的修改版.2011-01-01
.NET微服務(wù)架構(gòu)CI/CD自動(dòng)構(gòu)建Jenkins+Gitee
這篇文章介紹了.NET使用微服務(wù)架構(gòu)CI/CD自動(dòng)構(gòu)建Jenkins+Gitee的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01
asp.net實(shí)現(xiàn)在非MVC中使用Razor模板引擎的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)在非MVC中使用Razor模板引擎的方法,較為詳細(xì)的分析了Razor模板引擎的使用技巧,需要的朋友可以參考下2015-06-06

