exist.NET
Strongly typed string, which is not an official concept, is the coding practice of using a specific structure to represent certain types of string data. Similar to enumerations, it provides compile-time type checking, fewer runtime errors, and better readability and maintainability. Provides better scalability as well as stronger constraints than enumerations.
enumeration
Enumerations provide a convenient way to work with sets of related constants and associate constant values with names, offering the advantages of type safety, readability, and compile-time checking. However, enumerated types cannot define any methods, properties, or events; adding methods to enumerated types can only be simulated through the Extended Methods feature.
Although enumerations provide compile-time checks, there are limited constraints on the input values. For example, the following enumeration has four values and is of type int by default. The range of values is 0 ~ 3.
public enum Roles {
Author,
Editor,
Administrator,
SalesRepresentative
}
Then, there is a method that accepts a parameter of this enumerated type:
public string DoSomething(Roles role) {
return ();
}
Many developers may not check if the incoming value is actually a valid enum value. Any int type can be converted, and code like the following may appear:
var result = ((Roles)10);
The output is "10", and if there are branching statements or conditional judgments based on this enumeration in subsequent code, it will produce incorrect results. Strongly typed strings are a good choice for this situation.
Strongly typed strings (STRONGLY typed strings)
Strongly typed strings are to be declared as immutable value types (struct) with string constructors, i.e., they are to be declared with areadonly
modifier and implement theIEquatable<T>
Interface. To override the strongly typed stringToString()
method to return an implicit string value. and declares a known strongly typed string to that type via a static read-only attribute.
In order to make strongly typed strings look more like strings or enumerations in the language constructs of general-purpose code, it is necessary to override the equality operator for strongly typed strings.
here are.NET
Strongly typed string of the name of the cryptographic hash algorithm in the source codeHashAlgorithmNamecodes
using ;
namespace
{
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 ?? ;
}
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 (right);
}
public static bool operator !=(HashAlgorithmName left, HashAlgorithmName right)
{
return !(left == right);
}
//Other Extended Functions
public static bool TryFromOid(string oidValue, out HashAlgorithmName value)
{
(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.Cryptography_InvalidHashAlgorithmOid, oidValue));
}
}
}
This code better constrains the input of cryptographic hash algorithm names and extends other functionality as well. But it is quite a bit more cumbersome than enumeration.
According to the Framework Design Guide recommendations: when the base class supports a fixed set of input parameters, but the derived class needs to support more parameters, it is recommended to use strongly-typed strings; when used by sealed types only, only predefined values are needed and enumerations would be a better choice.
In addition, enumerations usually define closed sets of options, and strongly typed strings are also recommended for open sets such as operating system versions. Control LibrariesHandyControl
hit the nail on the headSystemVersionInfo
It is such an example.
consultation
Enum Alternatives in C# | Blog
Using Enumerated Classes (Instead of Enumerated Types) - .NET | Microsoft Learn