Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can C# Provide a static_assert?

Tags:

c#

I am looking for a way to have compile time assertions in the C# programming language, such as those provided by the BOOST library for C++, or the new C++0x standard.

My question is twofold; can this be achieved in standard, portable C#; Alternatively, can the behaviour be achieved via non-portable assumptions of the quirks of a given C# compiler?

A quick search on google revealed the following link to one technique, whose standards compliance and compatibility I am unsure of.

like image 963
grrussel Avatar asked Jun 08 '09 08:06

grrussel


2 Answers

The approach is the same as in other languages that don't have builtin static asserts (Delphi, older C++ and so on): find a mechanism to convert the condition to be asserted into something that the compiler is unhappy about if the condition is false.

For C# one of the easiest mechanisms to exploit is the warning regarding assignment of negative literals/constants to unsigned types. This has already been mentioned in passing somewhere in this discussion (or at least in one of the pages linked from here), but it is worth showing it in its pure form.

Here's an example that guards two constants - MODULUS_32 and MAX_N from being edited to values that violate expectations:

const uint _0 = (ulong)MODULUS_32 * MODULUS_32 == MAX_N ? 0 : -666;

The -666 makes the error message recognisable as being due to a static assert. Using the ternary operator in this context is preferrable to direct computations because this makes it easier to recognise what's going on (negative results in a computation are more likely to be ascribed to a mistake than explicit, deliberate assignment). Naming the constant something like _MAX_N_must_be_the_square_of_MODULUS_32 makes things even more explicit.

This type of 'static assert' halts compilation reliably - it's not just some warning that could get lost should someone tamper with the /warnaserror switch.

In certain scopes - for example, within functions - it can be necessary to suppress the 'unused value' warning via a pragma:

#pragma warning disable 219
const uint _0 = (ulong)MODULUS_32 * MODULUS_32 == MAX_N ? 0 : -666;
#pragma warning restore 219

C# is pretty much like Delphi in that it lacks a preprocessor, which means that the static asserts and their mechanisms cannot be packaged into neat macros - if you want to use them then you have to type all the plumbing right then and there. But just like in Delphi, the advantages of getting the compiler to check things at compile time are more than worth the small effort.

like image 170
DarthGizka Avatar answered Oct 05 '22 11:10

DarthGizka


Inside a function with a return value, the following trick/hack works (at least with Visual Studio 2005, haven't checked on other platforms):

Something Foo()
{
    if (compiletime_const_condition)
    {
        // ...
        return something;
    }

    // no return statement at all
}

It ain't pretty, but it's the best solution I have so far.

like image 6
Paul Groke Avatar answered Oct 01 '22 11:10

Paul Groke