.NET中,强类型字符串(Strongly typed string)并不是一个官方的概念,是指使用特定的结构来表示某种类型字符串数据的编码实践。类似于枚举,可以提供编译时检查类型,减少运行时错误,以及更好的可读性和维护性。相比于枚举,具有更好的扩展性以及更强的约束性。

枚举

枚举提供了一种便捷的方法来使用相关常数集并将常数值与名称相关联,具有类型安全、可读性高以及编译时检查等优点。但是枚举类型不能定义任何方法、属性或事件,只能通过扩展方法功能模拟向枚举类型添加方法。

尽管枚举提供了编译时检查,但对输入值的约束是有限的。例如,下面这个枚举有四个值,默认情况下是int类型。取值范围为0 ~ 3。

public enum Roles {
Author,
Editor,
Administrator,
SalesRepresentative
}

然后,有一个方法接受这个枚举类型的参数:

public string DoSomething(Roles role) {
return role.ToString();
}

许多开发人员可能不会检查传入值是否为实际有效的枚举值。任何int类型都可以转换,可能出现下边这种代码:

var result = myObject.DoSomething((Roles)10);

输出的结果是 “10”,如果后续代码中有基于这个枚举的分支语句或者条件判断,将产生错误的结果。对于这种情况,强类型字符串是一个不错的选择。

强类型字符串(Strongly typed string)

强类型字符串要声明成带有字符串构造函数的不可变值类型(struct),即要在该类型上用 readonly 修饰符,并为其实现 IEquatable<T> 接口。要覆写强类型字符串的 ToString() 方法,以返回隐式的字符串值。并将已知的强类型字符串通过静态只读属性声明到该类型上。

为了让强类型字符串在通用代码的语言结构上看起来更像字符串或者枚举,需要为强类型字符串覆写相等运算符。

以下就是 .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));
}
}
}

这段代码更好地约束了加密哈希算法名称的输入,同时还扩展了其他功能。但比枚举繁琐不少。

根据《框架设计指南》建议:当基类支持一组固定的输入参数,但是派生类需要支持更多的参数时,建议使用强类型字符串;当仅由密封类型使用时,只需要使用预定义的值,枚举将是更好的选择。

此外,枚举通常定义的是封闭的选项集,对于操作系统版本这种开放集合,也建议使用强类型字符串。控件库 HandyControl 中的 SystemVersionInfo正是这样的例子。

参考

Enum Alternatives in C# | Blog

使用枚举类(而不是枚举类型) - .NET | Microsoft Learn

什么是.NET的强类型字符串(Strongly typed string)?的更多相关文章

  1. Dynamic V Strongly Typed Views

    Come From https://blogs.msdn.microsoft.com/rickandy/2011/01/28/dynamic-v-strongly-typed-views/ There ...

  2. a loosely strongly typed language

    JavaScript: The Definitive Guide, Sixth Edition by David Flanagan As explained above, the following ...

  3. 字符串的使用(string,StringBuffer,StringBuilder)

    String中==与equals的区别:==比较字符串中的引用相等equals比较字符串中的内容相等(因为字符串有重写equals方法) string常用的方法 返回类型 方法 操作功能 Char c ...

  4. Swift_字符串详解(String)

    Swift_字符串详解(String) 类型别名 //类型别名 fileprivate func testTypeAliases() { let index = String.Index.self p ...

  5. C# 字符串比较大小 string.Compare()方法

    string.Compare方法,用来比较2个字符串值得大小 string.Compare(str1, str2, true); 返回值: 1 : str1大于str2 0 : str1等于str2 ...

  6. C风格字符串和C++ string 对象赋值操作的性能比较

    <<C++ Primer>> 第四版 Exercise Section 4.3.1 部分Exercise 4.2.9 习题如下: 在自己本机执行如下程序,记录程序执行时间: # ...

  7. C风格字符串和C++string对象的相互转化

    一.C风格的字符串转化为C++的string对象 C++中,string 类能够自动将C 风格的字符串转换成string 对象   #include <iostream> #include ...

  8. Android中五大字符串总结(String、StringBuffer、StringBuilder、Spanna

    https://www.aliyun.com/jiaocheng/2861.html?spm=5176.100033.1.35.2ed56b03CbsYFK 摘要:String.StringBuffe ...

  9. Java字符串池(String Pool)深度解析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在工作中,String类是我们使用频率非常高的一种对象类型.JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存 ...

  10. python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

随机推荐

  1. FastGPT 正式接入 Flux,准备好迎接 AI 绘画的狂风了么?

    Flux 大家最近都听说了吧?它是一款新推出的 AI 绘画模型,拳打 Stable Diffusion 3,脚踢 Midjourney,整个 AI 绘画界都沸腾了. Flux 的主创团队来自由 Sta ...

  2. SNERT内部集训-WEB

    SNERT内部集训-WEB Day1-2 文件上传 靶场搭建 docker安装,docker pull c0ny1/upload-labs,docker run -it -d -p 8080:80 a ...

  3. SQL Server 中的 NUL 设备/NIL设备

    SQL Server 中的 NUL 设备/NIL设备 在 SQL Server 中,有一个特殊的设备叫做 NUL(注意,不是 NULL),它类似于文件系统中的"黑洞".NUL 设备 ...

  4. Go runtime 调度器精讲(七):案例分析

    0. 前言 前面用了六讲介绍 Go runtime 调度器,这一讲我们看一个关于调度 goroutine 的程序案例分析下调度器做了什么.需要说明的是,这个程序和抢占有关,抢占目前为止还没有介绍到,如 ...

  5. 这10种分布式ID,太绝了!

    前言 分布式ID,在我们日常的开发中,其实使用的挺多的. 有很多业务场景在用,比如: 分布式链路系统的trace_id 单表中的主键 Redis中分布式锁的key 分库分表后表的id 今天跟大家一起聊 ...

  6. 在C#中使用适配器Adapter模式和扩展方法解决面向的对象设计问题

    之前有阵子在业余时间拓展自己的一个游戏框架,结果在实现的过程中发现一个设计问题.这个游戏框架基于MonoGame实现,在MonoGame中,所有的材质渲染(Texture Rendering)都是通过 ...

  7. 配置 ZRAM,实现 Linux 下的内存压缩,零成本低开销获得成倍内存扩增

    由于项目需求,笔者最近在一台 Linux 服务器上部署了 ElasticSearch 集群,却发现运行过程中经常出现查询速度突然降低的问题,登录服务器后发现是物理内存不足,导致机器频繁发生页面交换.由 ...

  8. 利用 ACME 实现SSL证书自动化配置更新

    最近收到腾讯云的通知SSL证书要到期了,本想直接申请的发现现在申请的免费SSL证书有效期只有90天了,顺便了解了一下原因是包括Google在内的国际顶级科技公司一直都有在推进免费证书90天有效期的建议 ...

  9. 调查报告解读之国外数据库篇:MySQL国内使用率第一,多少企业有意替换国外产品?

    为了解数据库行业以及从业人员的现状.数据库选型.中国数据库的发展趋势等,墨天轮于2022年开始进行问卷收集,历时24天,共征集到有效问卷3476份,并于2月10日整理发布了<2022年墨天轮数据 ...

  10. 在实例化对象的时候new关键字具体做了哪些操作?

    a 创建了一个空对象 {}b 通过原型链把空对象和构造函数连接起来__proto__ = prototype c 构造函数的this指向新对象,并执行函数体 d 判断构造函数的返回值,返回对象就使用该 ...