DotNext by Roman Sakno

<PackageReference Include="DotNext" Version="2.4.0" />

 Constant<T>

public abstract class Constant<T> : IConvertible<T>
Allows to use constant values as generic parameters.
using System.Runtime.CompilerServices; namespace DotNext.Generic { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public abstract class Constant<[System.Runtime.CompilerServices.Nullable(2)] T> : IConvertible<T> { public T Value { get; } protected Constant(T constVal) { Value = constVal; } T IConvertible<T>.Convert() { return Value; } public sealed override string ToString() { T value = Value; ref T reference = ref value; T val = default(T); object obj; if (val == null) { val = reference; ref reference = ref val; if (val == null) { obj = null; goto IL_0038; } } obj = reference.ToString(); goto IL_0038; IL_0038: if (obj == null) obj = "NULL"; return (string)obj; } public sealed override int GetHashCode() { T value = Value; ref T reference = ref value; T val = default(T); if (val == null) { val = reference; ref reference = ref val; if (val == null) return 0; } return reference.GetHashCode(); } [System.Runtime.CompilerServices.NullableContext(2)] public sealed override bool Equals(object other) { if (!(other is T)) { Constant<T> constant = other as Constant<T>; if (constant != null) return object.Equals(Value, constant.Value); return false; } T val = (T)other; return object.Equals(val, Value); } public static implicit operator T([System.Runtime.CompilerServices.Nullable(new byte[] { 2, 1 })] Constant<T> const) { if (const != null) return const.Value; return default(T); } } }