The Const Type Args framework provides libraries, samples, and documentation to support working with const type arguments. Const type arguments, or const type args, are used to effectively "pass" compile-time-like values to generic types & methods via generic parameters and accessible in static contexts such as type initialization, and static methods, fields, & properties.
Const type args provide a number of inherent and derived benefits, including:
-
Static polymorphism - Similar to template specialization in C++, const type arguments can provide implementations to arg consumer types, enabling compile-time specialization and avoiding virtual dispatch and other runtime overhead polymorphism typically incurs.
-
Increased type safety - Various techniques can ensure const type args only supply arg consumers with valid values. This reduces the risks of invalid configurations, mismatched types, and other runtime issues. Some techniques include validation during type initialization, using highly specific generic constratins, and even static analysis tools.
-
Type configuration - Const type args can be used to configure types of arg consumers which can avoid needlessly passing configuration values, redundant validation, and improve readability & expressivness by replacing "magic numbers" with descriptive type names.
-
Reduced test boilerplate - Testing different const type arg configurations is as simple as replacing generic type & method arguments, helping reduce mock setup and repetitive test code.
-
Additonal reusablitity - Const type args can be defined once and used in multiple const type arg configurations, reducing code duplication. Similarly, arg consumers can be extended with new const type arg types instead of new classes.
-
Design pattern enhancements - Patterns like State Machines and Entity Component Systems (ECS) can benefit from strongly typed, predefined values that make transitions and components type-safe.
Const type args can be used in a variety of different scenarios, soem of which include:
-
Type-safe configuration - Enforce constraints on buffer sizes, timeouts, or thread limits by ensuring only valid const type arguments can be used.
-
Implementation selection - Configure specialized versions of a generic type (e.g.,
SmallBuffer
,MediumBuffer
,LargeBuffer
) for different performance profiles. -
Domain-specific values - Integrate domain constants (e.g., currency, units of measurement) into the type system to guarantee consistency across your codebase.
-
Parameterized callbacks & events - Provide predefined values or delegates as part of event handlers or callbacks, preventing unexpected inputs at runtime.
-
Units of measure - Encode measurement units (length, time, temperature) directly into the type system, reducing runtime conversion errors.
-
State Machines & RegEx Patterns - Model valid state transitions or store regex patterns in const type arguments, ensuring they’re validated and discoverable throughout the application.
-
Union-Like Types - Emulate union behaviors by allowing a generic type to accept multiple const type arguments, making your code both flexible and safe.
-
and more!
Check out the available samples for in-depth examples of const type args in action.
Using const type args is simple. First, define a type implementing IConstTypeArg<T>
and have the Value
property return the value you want to "pass" with a generic argument. Then, for any generic type or method, use the const type arg you defined as a generic argument constrained to a type of IConstTypeArg<T>
(i.e., a const type parameter).
Defining const type args
using ConstTypeArgs;
public readonly struct _32 : IConstTypeArg<int>
{
public static int Value => 32;
}
// Assume similar definitions for _1024, True, False.
Usage Example:
public class Buffer<T, TSize>
where TSize : IConstTypeArg<int>
{
public T[] Data = new T[TSize.Value];
}
// Instantiating buffers with different "constant" sizes:
var smallBuffer = new Buffer<int, _32>(); // length == 32
var bigBuffer = new Buffer<int, _1024>(); // length == 1024
-
Const type argument - A type (implementing
IConstTypeArg<T>
) that provides a staticValue
and is passed as a generic argument. Sometimes called const type arg or argument provider. -
Const type parameter - A generic parameter constrained to a type implementing
IConstTypeArg<T>
. Sometimes called const type param. -
Argument holder - A const type argument that wraps or composes other const type arguments, typically implementing
K<T, TArg>
.
For more definitions, see the Glossary.
Convention | Description |
---|---|
K_ Prefix |
Used for interfaces deriving from IConstTypeArg<T> , indicating they represent a “constant” in mathematical form. |
_ Prefix |
Used for concrete types (e.g., _32 , _A , _Blue ) that implement IConstTypeArg<T> . This groups similar constants and clarifies each value’s role. |
__ Types |
These are discards (e.g., __ ) that may implement multiple const type arg interfaces, effectively providing union-like behavior with default/null values. |
Explore more in the Documentation folder, including: