Creative Minds

Because we all have one

TIP: Conditional code execution with the ConditionalAttribute and the #IF … #ENDIF Preprocessor Directive

While developing an application, you need to execute some code only when a defined condition is meet, for example, you have a product and you want to have specific code execution for both a release version and a trial version. You could change the code and compile different code for each version, or you could use one (or both) of the following solutions:

  • The ConditionalAttribute indicates that a method is callable if a specified preprocessing identifier is applied to the method.
  • The #IF … #ENDIF Preprocessor Directive conditionally includes source code at compile-time if a specified preprocessing identifier is defined.

The ConditionalAttribute class

An practical example of the usage of this attribute is the framework itself. The System.Diagnostics.Debug class uses in its methods this attribute so that when you are debugging your assembly, the debugging information is output:

image

Let build a simple example:

using

 System;

using

 System.Collections.Generic;
using

 System.Diagnostics;

public

 class

 MyConditionalSample
{
    public

 static

 void

 Main()
    {
        Debug.WriteLine("Some debug info!"

);
        ExecuteIfRelease();
        ExecuteIfDebug();
    }

    [Conditional("RELEASE"

)]
    private

 static

 void

 ExecuteIfRelease()
    {
        Console.WriteLine("Hello world! I'm a release assembly!"

);
    }

    [Conditional("DEBUG"

)]
    private

 static

 void

 ExecuteIfDebug()
    {
        Console.WriteLine("Hello world! I'm a debug assembly!"

);
    }

}

This is a straight forward example. In the Main method we call the Debug.WriteLine method to output some debug info, and call both ExecuteIfRelease and ExecuteIfDebug methods.

Looking at these methods, notice that they have the Conditional attribute with the conditional compilation symbols RELEASE and DEBUG.

So, on our command line we will first simple compile and execute our code:

image

As you can see, no output was wrote, this because no conditional symbols were defined in our compilation. Let’s change our compilation command to include the RELEASE symbol:

image

Now that we added the RELEASE symbol, the runtime now executes our ExecuteIfRelease method.

Changing the symbol to DEBUG will now make the runtime execute the ExecuteIfDebug method and also output our debug message, that we can trace in the DebugView:

image

image

If we look at our compile code in the .NET Reflector we will see that both methods are declared on the code but only the ExecuteIfDebug method is declared on the Main method:

image

#IF … #ENDIF Preprocessor Directive

The #IF…#ENDIF preprocessor takes this to another level. When using this directive, you are telling the compiler to include/exclude code from the compiled assembly.

So, taking our example and changing it to use instead this directive:

using

 System;

using

 System.Collections.Generic;
using

 System.Diagnostics;

public

 class

 MyConditionalSample
{
    public

 static

 void

 Main()
    {
        Debug.WriteLine("Some debug info!"

);
        #if

(RELEASE)
        ExecuteIfRelease();
        #elif(DEBUG)
        ExecuteIfDebug();
        #endif

    }

    #if

(RELEASE)
    private

 static

 void

 ExecuteIfRelease()
    {
        Console.WriteLine("Hello world! I'm a release assembly!"

);
    }
    #elif(DEBUG)
    private

 static

 void

 ExecuteIfDebug()
    {
        Console.WriteLine("Hello world! I'm a debug assembly!"

);
    }
    #endif

}

Now let’s compile and execute our code using the DEBUG symbol:

image

The code executed has expected, with no visible difference from the prior sample. So what’s the catch?

The catch, has told, is in the compiled code itself:

image

Notice that our compiled code doesn’t include the ExecuteIfRelease method.

Conclusion

So there you have it. To simple ways of call conditional code. One more thing: although we used the command line compiler to define de conditional symbols, the same can be made using Visual Studio. Simply go to the project’s properties, and on the Build tab set your custom compilations symbols, or use the DEBUG and/or TRACE symbols:

image

I would like to say thanks to my good friend Paulo for pointing me into the right direction on this matter.

 Digg  Facebook  StumbleUpon  Technorati  Deli.cio.us 

Tagged as , , , + Categorized as Tips & Tricks

Leave a Reply