#if vs. ConditionalAttribute

At BataviaLabs we were debating coding guidelines the other day and came across this one: do you use #if or the ConditionalAttribute to indicate to the compiler if a method should be compiled. Let me elaborate…


If you have a method you only want to compile in a debug scenario, you have the following options:


1) Use #if DEBUG as shown below

class Program
{
static void Main(string[] args)
{
#if DEBUG
SomeMethod();
#endif
Console.WriteLine(“End”);
Console.ReadKey();
}

#if DEBUG
internal static void SomeMethod()
{
Console.WriteLine(“SomeMethod”);
}
#endif
}


2) Use the ConditionalAttribute as shown below

class Program
{
static void Main(string[] args)
{
SomeMethod();
Console.WriteLine(“End”);
Console.ReadKey();
}

[Conditional(“DEBUG”)]
internal static void SomeMethod()
{
Console.WriteLine(“SomeMethod”);
}
}


The difference between these two methods is enormous. The first sample is very explicit. Any code you don’t want to compile into the production build is placed between #if DEBUG and #endif. If you try to call SomeMethod in a production build, the compiler will give you a compile error. The ConditionalAttributeon the other hand doesn’t require you to remove the calls to SomeMethod. If a method is marked [Conditional], any calls made to that method are removed from the build by the compiler. A proviso here is that [Conditional] only works with methods that don’t return a value (i.e. void).


I much more prefer #if DEBUG, because it is explicit. I can’t run into a situation where from reading the code I’m thinking “SomeMethod is being executed”, but it actually isn’t because the compiler removed the call. Comments anyone?

One thought on “#if vs. ConditionalAttribute

  1. Ralph Coesmans

    I also prefer the #if DEBUG. You have to be careful though when using refactoring tools. They don’t see both sides of the optional #if, so when it is used in the form:


    #if DEBUG
    some debug code;

    #else
    some release code;

    #endif

    Then the refactoring tool of your choice might alert you of the fact that unused code can be removed, even some unused references/methods or namespace usings, which can then be removed/refactored causing problems in the release.

    So take care when using #if DEBUG and keep the conditional parts as small and atomic as possible (so with quick reads/scans the intention is instantly clear). Add comments to possibly related codeparts/references/usings that can be incorrectly refactored…

    AND use automatic buildtools and unittests to build, test and guard these specific conditional parts in debug/test/release modes.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *