ConstTypeArgs.Core 1.2.0-beta1

This is a prerelease version of ConstTypeArgs.Core.
There is a newer version of this package available.
See the version list below for details.
dotnet add package ConstTypeArgs.Core --version 1.2.0-beta1                
NuGet\Install-Package ConstTypeArgs.Core -Version 1.2.0-beta1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ConstTypeArgs.Core" Version="1.2.0-beta1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ConstTypeArgs.Core --version 1.2.0-beta1                
#r "nuget: ConstTypeArgs.Core, 1.2.0-beta1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install ConstTypeArgs.Core as a Cake Addin
#addin nuget:?package=ConstTypeArgs.Core&version=1.2.0-beta1&prerelease

// Install ConstTypeArgs.Core as a Cake Tool
#tool nuget:?package=ConstTypeArgs.Core&version=1.2.0-beta1&prerelease                

ConstTypeArgs.Core

The ConstTypeArgs.Core library provides the basic types needed to create const type arguments, which are types used to pass values to generics through their generic parameters. These values can be used in static contexts, such as for static constructors, field initialization, and more.

Framework Overview

The ConstTypeArgs framework allows you to work with const type arguments (also called const type args), which use generic parameters to "pass" constant-like values to generics. These values are can be used in static contexts, such as static constructors, static fields, and static methods. This can mimic C++ template specialization, provide enhanced type safety, static polymorphism, increased expressiveness, and more.

Benefits

There are many benefits to using const type arguments, such as:

  • Type Safety
  • Static Polymorphism
  • Flexible Validation
  • Domain Specific Types
  • Improved Readability & Expressiveness
  • Flexible & Reusable Components
  • Enhanced Debugging
  • Improved Unit Testing

These are just some of the benefits the ConstTypeArgs framework can provide. For more information, go to Benefits in the framework documentation.

Use Case Scenarios

Const type arguments can be used in a variety of scenarios to provide enhanced type safety, static polymorphism, increased expressiveness, and more. Some ways const type arguments can be used include:

  • Buffer Size Specification
  • Type Configuration
  • Implementation Selection
  • Union-Like Types
  • Units of Measure
  • Type-Safe State Machines
  • Event Handlers as Types
  • RegEx Patterns as Types
  • Enum-Like Types
  • Design Pattern Enhancement
  • ECS (Entity-Component-System) Integration
  • Type Mapping

These are just some of the use cases where const type arguments can be used to provide enhanced type safety, static polymorphism, increased expressiveness, and more. For more information, go to Use Cases in the framework documentation.

Defining & Using Const Type Arguments

Defining a const type argument is as simple as:

using ConstTypeArgs;

public readonly struct _32 : IConstTypeArg<int>
{ public static int Value => 32; }

And using it is as simple as:

public class Buffer<T, TSize>
    where TSize : IConstTypeArg<int>
{
    public T[] Data = new T[TSize.Value];
}

var smallBuffer = new Buffer<int, _32>();
// smallBuffer.Data.Length == 32

var bigBuffer = new Buffer<int, _1024>();
// bigBuffer.Data.Length == 1024

Glossary

These are some of the common terms used throughout the ConstTypeArgs documentation:

  • Const Type Argument - A type that uses generic parameters to "pass" values to generics. This term is interchangeable with the value they hold unless ambiguity arises, in which case argument provider and argument value are used.

  • Const Type Parameter: - A generic parameter that const type arguments "pass" values through.

  • Argument Holder - A const type argument that wraps other const type arguments. These are useful for reusing domain-specific values.

Go to the framework documentation Glossary for more details and terminology.

Types

At the ConstTypeArgs framework's very core is the interface IConstTypeArg<T>. This type only contains a single member: the static abstract property Value. This type isn't special by itself, however it is the foundational type which the framework is built upon.

[!NOTE] IConstTypeArg<T> implements the marker interface IConstTypeArg which in some cases can benefit type test.

IConstTypeArg<T, TSelf> is a related type and inherits from IConstTypeArg<T>. This type allows const type argument instantiation in the rare cases this is needed.

This is used to create a set of core interfaces, such as K, K_Array<T>, K_Class<T>, K_Integer, K_Delegate<T>, K_Unmanaged_<T>, and others that are used as constraints and are further built upon in other ConstTypeArgs libraries.

For more information, go to Types.

Naming Conventions

The ConstTypeFramework modifies standard naming conventions in order to provide a more expressive and readable codebase, outlined in the following table:

Convention
K_ Prefix The names of argument interfaces (i.e. interfaces deriving from IConstTypeArg<T>) use this prefix. This is meant to indicate that rather than define a contract, they are the means to "pass" values via generic type parameters. The prefix refers to how K is used in mathematic formulas to denote an unknown constant value.
_ Prefix Many argument providers (i.e. concrete types that implement IConstTypeArg<T>) in ConstTypeArg libraries have the prefix _ followed by a representation of their value (e.g. _1024, _A, _Blue). This helps alphabetize and group similar types together.
__ Types Argument types (i.e. types deriving from or implementing IConstTypeArg<T>) that implement __ are used as "discards" to indicate they lack a value. These types are simply named __ and usually explicitly implement multiple arg type interfaces and provide either default or null values. These can be used with argument consumers providing union-like behavior.

Installation

To install the ConstTypeArgs.Core library, run the following command in the Package Manager Console:

dotnet add package ConstTypeArgs.Core

License

The ConstTypeArgs.Core library is licensed under the MIT License. See the LICENSE file for more details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (20)

Showing the top 5 NuGet packages that depend on ConstTypeArgs.Core:

Package Downloads
ConstTypeArgs.Ints

Builds on type of the ConstTypeArgs.Core library to provide const type arguments that allow you to use type parameters to pass int values to generics at compile-time. This provides an analog to type specialization in C++, and can be used for scenarios such as: * Static configuration, * Eliminating unnecessary instance constructors, * "Passing" values to type initializers, * And more. Built-in const type arguments cover -1 to -15, 0 to 15, powers of 2 up to 65536, and more. Here's a simple demonstration showing how to define and use const type arguments and domain-specific type arguments: using ConstTypeArgs.Ints; // Const type arguments: public readonly struct _8 : K_Int<_8> { public static int Value => 8; } public readonly struct _32 : K_Int<_32> { public static int Value => 32; } public abstract class DefaultSize : Int<_32> { } // Usage: public class Foo<TSize> where TSize : K_Int { public static readonly int[] FooArray = new int[TSize.Value]; static Foo() { Console.WriteLine($"Array size is {FooArray.Length}"); } } // Elsewhere var foo = new Foo<_8>(); // Outputs "Array size is 8" foo = new Foo<DefaultSize>(); // Outputs "Array size is 32"

ConstTypeArgs.UInt128s

Builds on type of the ConstTypeArgs.Core library to provide const type arguments that allow you to use type parameters to pass UInt128 values to generics at compile-time. This provides an analog to type specialization in C++, and can be used for scenarios such as: * Static configuration, * Eliminating unnecessary instance constructors, * "Passing" values to type initializers, * And more. Built-in const type arguments include values for 0 to 16 and others. Here's a simple demonstration showing how to define and use const type arguments and domain-specific type arguments: using ConstTypeArgs.UInt128s; // Const type arguments: public readonly struct _8 : K_UInt128<_8> { public static UInt128 Value => 8; } public readonly struct _64_000 : K_UInt128<_64_000> { public static UInt128 Value => 64000; } public abstract class DefaultSize : UInt128<_64_000> { } // Usage: public class Foo<TSize> where TSize : K_UInt128 { public static readonly UInt128 BigArraySize = TSize.Value; // Code to initialize very large arrays. static Foo() { Console.WriteLine($"Big array size is {BigArraySize.Length}"); } } // Elsewhere var foo = new Foo<_8>(); // Outputs "Big array size is 8" foo = new Foo<DefaultSize>(); // Outputs "Big array size is 32"

ConstTypeArgs.Bytes

Builds on type of the ConstTypeArgs.Core library to provide const type arguments that allow you to use type parameters to pass byte values to generics at compile-time. This provides an analog to type specialization in C++, and can be used for scenarios such as: * Static configuration, * Eliminating unnecessary instance constructors, * "Passing" values to type initializers, * And more. Built-in const type arguments include values for 0 - 10, powers of 2, min & max values, and others. Here's a simple demonstration showing how to define and use const type arguments and domain-specific type arguments: using ConstTypeArgs.Bytes; // Const type arguments: public readonly struct _8 : K_Byte<_8> { public static byte Value => 8; } public readonly struct _32 : K_Byte<_32> { public static byte Value => 32; } public abstract class InitialValue : Byte<_32> { } // Usage: public class Foo<TSize> where TSize : K_Byte { public static readonly int[] FooArray = new int[TSize.Value]; static Foo() { Console.WriteLine($"Array size is {FooArray.Length}"); } } // Elsewhere var foo = new Foo<_8>(); // Outputs "Array size is 8" foo = new Foo<InitialValue>(); // Outputs "Array size is 32"

ConstTypeArgs.Ulongs

Builds on type of the ConstTypeArgs.Core library to provide const type arguments that allow you to use type parameters to pass ulong values to generics at compile-time. This provides an analog to type specialization in C++, and can be used for scenarios such as: * Static configuration, * Eliminating unnecessary instance constructors, * "Passing" values to type initializers, * And more. Built-in const type arguments cover 0 to 15, powers of 2 up to 65536, and more. Here's a simple demonstration showing how to define and use const type arguments and domain-specific type arguments: using ConstTypeArgs.Ulongs; // Const type arguments: public readonly struct _8 : K_Ulong<_8> { public static ulong Value => 8; } public readonly struct _32 : K_Ulong<_32> { public static ulong Value => 32; } public abstract class DefaultSize : Ulong<_32> { } // Usage: public class Foo<TSize> where TSize : K_Ulong { public static readonly int[] FooArray = new int[TSize.Value]; static Foo() { Console.WriteLine($"Array size is {FooArray.Length}"); } } // Elsewhere var foo = new Foo<_8>(); // Outputs "Array size is 8" foo = new Foo<DefaultSize>(); // Outputs "Array size is 32"

ConstTypeArgs.Types

Builds on types of the ConstTypeArgs.Core library to provide const type arguments that allow you to use type parameters to pass Type values to generics at compile-time. This provides an analog to type specialization in C++. Here's a simple demonstration: using ConstTypeArgs.Types; public class Foo<TType> { static Foo() { if (TType.Value == typeof(string) || TType.Value == typeof(char) || TType.Value == typeof(char[]) || TType.Value == typeof(ReadOnlyMemory<char>) || TType.Value == typeof(ReadOnlySpan<char>)) { Console.WriteLine($"{TType.Value} values usually represent text!"); } if (TType.Value == typeof(byte) || TType.Value == typeof(sbyte) || TType.Value == typeof(short) || TType.Value == typeof(ushort) || TType.Value == typeof(int) || TType.Value == typeof(uint) || TType.Value == typeof(long) || TType.Value == typeof(ulong) || TType.Value == typeof(nint) || TType.Value == typeof(nuint)) { Console.WriteLine($"{TType.Value} values usually represent numbers!"); } } } // Elsewhere, assuming the value of StringType is typeof(string) var foo = new Foo<StringType>(); // Outputs: StringType values usually represent text! // Assuming that the value of IntType is typeof(int) foo = new Foo<IntType>(); // Outputs: TType values usually represent numbers! Here's how you could create a new Type const type argument: public readonly struct StringType : K_Type<StringType> { public static Type Value => typeof(string); }

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.2.0 114 8/27/2024
1.2.0-beta1 112 8/20/2024
1.0.0 291 7/1/2024

Added types of exceptions: ConstTypeException, ConstTypeArgException, UndefinedConstTypeArgException, and MisleadingConstTypeException.
   Fixed K_ReadOnlyMemoryT_Array<T> to implement K_ReadOnlyMemory<T[]> instead of K_Array<T>.
   Miscellaneous minor changes.