LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

什么是.NET的强类型字符串(Strongly typed string)?

freeflydom
2024年12月5日 9:36 本文热度 224

.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

转自https://www.cnblogs.com/czwy/p/18576931


该文章在 2024/12/5 9:40:23 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved