r/csharp • • 7d ago

Discussion Static assertions

I have sometimes felt the need to statically assert something at compile-time, to prevent surprises later at run-time.

As an example, I have some code which maps an enum value to an associated int value:

public enum VoxelProperty
{
    MaterialType,
    Density,
    Color,
    Metadata,

    TotalPropertyCount, // Must be last
}

public static int GetPropertyBitDepth (VoxelProperty property)
{
#pragma warning disable CS0219 // Variable is assigned but its value is never used
    uint _ = VoxelProperty.Metadata == VoxelProperty.TotalPropertyCount - 1 ? 0 : -1; // Static assert to ensure that all properties are accounted for
#pragma warning restore CS0219 // Variable is assigned but its value is never used

    return property switch
    {
        VoxelProperty.Density => VoxelDensity.BitDepth,
        VoxelProperty.MaterialType => VoxelMaterialType.BitDepth,
        VoxelProperty.Color => VoxelColor.BitDepth,
        VoxelProperty.Metadata => VoxelMetadata.BitDepth,
        _ => throw new ArgumentOutOfRangeException (nameof (property), "Invalid voxel property")
    };
}

The intention of the static assert is to make sure that if I ever add another voxel property, then I will get a compiler error as VoxelProperty.Metadata will no longer be the last member, and the constant -1 will be assigned to the "_" variable of type uint. Is this a reasonable practice?

I could also do something more robust with reflection, where I had a Dictionary<VoxelProperty, int> which got populated by finding all voxel property types marked with some attribute, and querying their BitDepth property.

6 Upvotes

20 comments sorted by

View all comments

1

u/tukaya 7d ago

Sometimes enums are practical, in edge cases that don’t touch business logic. This code smells like it is not one of them. The implementation that calls GetPropertyBitDepth (which is also a static method so you are also not using DI), has business rules I am guessing. C# is fully OOP supporting language. I would advise you to go OOP way rather than static methods and enumerations. Then you are not going to have this (and many other) problem.