什么是.NET的强类型字符串(Strongly typed string)?
在.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)?的更多相关文章
- Dynamic V Strongly Typed Views
Come From https://blogs.msdn.microsoft.com/rickandy/2011/01/28/dynamic-v-strongly-typed-views/ There ...
- a loosely strongly typed language
JavaScript: The Definitive Guide, Sixth Edition by David Flanagan As explained above, the following ...
- 字符串的使用(string,StringBuffer,StringBuilder)
String中==与equals的区别:==比较字符串中的引用相等equals比较字符串中的内容相等(因为字符串有重写equals方法) string常用的方法 返回类型 方法 操作功能 Char c ...
- Swift_字符串详解(String)
Swift_字符串详解(String) 类型别名 //类型别名 fileprivate func testTypeAliases() { let index = String.Index.self p ...
- C# 字符串比较大小 string.Compare()方法
string.Compare方法,用来比较2个字符串值得大小 string.Compare(str1, str2, true); 返回值: 1 : str1大于str2 0 : str1等于str2 ...
- C风格字符串和C++ string 对象赋值操作的性能比较
<<C++ Primer>> 第四版 Exercise Section 4.3.1 部分Exercise 4.2.9 习题如下: 在自己本机执行如下程序,记录程序执行时间: # ...
- C风格字符串和C++string对象的相互转化
一.C风格的字符串转化为C++的string对象 C++中,string 类能够自动将C 风格的字符串转换成string 对象 #include <iostream> #include ...
- Android中五大字符串总结(String、StringBuffer、StringBuilder、Spanna
https://www.aliyun.com/jiaocheng/2861.html?spm=5176.100033.1.35.2ed56b03CbsYFK 摘要:String.StringBuffe ...
- Java字符串池(String Pool)深度解析
版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在工作中,String类是我们使用频率非常高的一种对象类型.JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存 ...
- python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...
随机推荐
- TypeScript – Work with JavaScript Library (using esbuild)
前言 JavaScript 早期是没有 Modular 和 Type (类型) 的. 随着这几年的普及, 几乎有维护的 Library 都有 Modular 和 Type 了. 但万一遇到没有 Mod ...
- ASP.NET Core – Case Style Conversion
前言 之前就有写过一篇 <<前后端沟通 naming conversion 转换需要知道的事>> 这篇做一个总结整理. 我们知道 C# 的 Property 是 PascalC ...
- MyBatis——注解开发
注解开发完成增删改 * (在完成简单功能时)使用注解开发会比配置文件开发更加方便 查询:@Select 添加:@Insert 修改:@Update 删除:@Delete ...
- 新手指南-新人入职-maven相关
一.前言 入职后,发现公司是用Maven对项目进行管理和构建. 一般来说,自己先确定以下几点: 1.公司对版本是否有要求. 2.是否要求IDEA对maven有特殊的配置. 3.确定自己的 MAVEN_ ...
- 在windows下安装Composer(转载)
在windows下安装Composer Composer是 PHP 用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer ...
- Ftrace 进阶用法
1 前言 本文为 Ftrace 系列文章第二篇,描述 Ftrace 进阶用法.上一篇文章中我们接触到了 Ftrace 基本概念,知道了如何 trace 一个函数,知道了如何 enable 一个 tra ...
- MYSQL存储过程-练习5 游标
MYSQL存储过程-练习5 游标 1 DELIMITER $ 2 CREATE PROCEDURE sp_cur() 3 BEGIN 4 DECLARE bkname VARCHAR(200); 5 ...
- kali Linux及mac os 破解WiFi
wpa-dictionary 用于 Wi-Fi 密码破解. Linux 篇(推荐) 1. 安装 aircrack-ng 使用相应包管理工具安装,例如 Debian/Ubuntu 使用 apt 安装: ...
- 一些新奇的玩意【php篇--持续更新】
人不进步就等于退步! 接触越多的人以及事就能学到更多的东西. 以下仅为本人记录的一些新奇的东西,不喜勿喷! 1.??运算符号,在新的项目中突然发现很多红线报错,还以为是错误!看了下,是??运算的问题, ...
- VScode如何设置浅色侧栏
原文地址:https://blog.csdn.net/KaiSarH/article/details/113241334 vscode主题设置成了浅色,但是侧边栏仍然是灰色,非常讨厌. 在设置中对&q ...