zacharylayne / ConstTypeArgs

Provides a framework for defining types that can be used to pass constant & static values as generic type arguments. These can be used in static contexts (such as static constructors & static methods), reduce the need to pass arguments through instance constructors, add compile-time validation, and more.
MIT License
2 stars 0 forks source link
constants csharp dotnet generics

ConstTypeArgs Framework

The ConstTypeArgs framework provides everything needed to work with const type arguments. Const type arguments, or const type args, are types that use generic parameters to conceptually "pass" const-like values to generics. These values are available directly through the generic parameters, allowing them to be used in static contexts (i.e. static constructors, static fields, static methods, static anonymous functions, etc.), to initialize fields, inside property & event accessors, and in parameterless constructors & instance methods, as well other scenarios.


The framework is written in C# 11 and targets .NET 8.0. Be aware that the framework is still in development and many features are still being added.


Benefits

There are many benefits to using const type arguments, including:

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:

For more information on use cases, go to Use Cases in the framework documentation.


Defining & Using Const Type Arguments

NOTE: The term const type argument is used for simplicity, to tie together related terminology, & to imply intent. Const type arguments are not true constants, but rather types that provide a constant-like, immutable value to generics and are not available at compile-time.

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


Terminology

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

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

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.

Further Documentation

Further documentation can be found in the Documentation directory.