views:

274

answers:

7

Say I have the following code snippet in c#

static const bool DO_PERFORMANCE_CODE = false;

if (DO_PERFORMANCE_CODE)
{
   // performance monitoring code goes here
}

Will that code get removed by the compiler? This is the functionality I'd like. Basically I want to mimic the conditional compilation stuff in C#, but I want more configurations other than Release and Debug. If there is a better way of doing this, I'd be open to hearing it.

+8  A: 

When you build in "debug" the preprocessor variable DEBUG is defined. So, you can do this:

public void MyFunc()
{
//do release stuff
#if DEBUG
//do performance testing
#endif
//finish release stuff
}

and it will be ignored by the compiler when you switch to Release mode.

Alternatively, you can define your own preprocessor variable if you don't want to test in debug mode, making sure to "#define PERFORMANCE_TESTING" when you want to test, and commenting it out when you don't.

#define PERFORMANCE_TESTING

    public void MyFunc()
    {
    //do release stuff
    #if PERFORMANCE_TESTING
    //do performance testing
    #endif
    //finish release stuff
    }
scottm
I thought when I saw your answer you only had the #if DEBUG part in there. I'll give you an upvote since he said he wanted more than DEBUG and release.
Aaron Smith
Honestly, I did. Then I realized if you are focused on performance, you might want to do testing in release mode.
scottm
Is it possible to have nested #ifs? I would assume so, but I'm not sure.
Jonathan Beerhalter
Yes, you can nest multiple preprocessor directives.
scottm
And it can get very hard to follow very quickly
danio
The [Conditional] attribute is also nice when your performance code is in a method.
sixlettervariables
+1  A: 

You can define your own precompiler variables.

 #define temp

 #if temp
 // Do something
 #endif
Aaron Smith
+1  A: 

you can define your own constants either at the top of the file:

 #define SUPERDOOPERDEBUG

 using System;

 ....


 #if SUPERDOOPERDEBUG

     // something

 #endif

Also, you can set up different build configurations than just 'release' and 'debug' (See the Build -> Configuration menu or define additional Conditional compilation symbols in the Project -> properties menu

Jimmy
Wow, I was 14 seconds ahead of you.
Aaron Smith
I'll get you next time, Inspector Gadget!
Jimmy
And you get upvoted and I don't. :-(
Aaron Smith
A: 

You can define more symbols other than DEBUG/RELEASE ... just look in the project properties :-) then you can use the preprocessor directive syntax to optionally include things based on the project configuration

Joel Martinez
A: 

You aren't limited to DEBUG and RELEASE. You can specify other constants with #define or in the project properties.

lc
Ha. #5 with the same answer. Sorry to clutter.
lc
+3  A: 

Defining your own symbols is probably cleaner, but I was curious as to what the compiler would do, so I did some experimenting (using VS 2008 in release mode).

With this:

class Program
{
    static void Main(string[] args)
    {
        bool foo = false;

        if (foo)
        {
            Console.WriteLine("Hello, world?");
        }
    }
}

The compiler still generates the code for the if statement:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       16 (0x10)
  .maxstack  1
  .locals init ([0] bool foo)
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  ldloc.0
  IL_0003:  brfalse.s  IL_000f
  IL_0005:  ldstr      "Hello, world\?"
  IL_000a:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_000f:  ret
} // end of method Program::Main

If instead you do:

class Program
{
    static void Main(string[] args)
    {
        bool foo = false;

        if (false)
        {
            Console.WriteLine("Hello, world?");
        }
    }
}

It doesn't generate code for the if statement:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       1 (0x1)
  .maxstack  8
  IL_0000:  ret
} // end of method Program::Main

It also seems to skip the variable that is assigned a value that is never used.

I checked with ildasm.exe, the disassembler that comes with visual studio.

Dana
+2  A: 

I ran a bunch of tests with Reflector and Visual Studio 2008 SP1, and this is what I found.

  1. Inside of a false conditional compilation (#if SOMETHING_FALSE...), the code is not only not compiled, but the compiler doesn't even complain about errors
  2. In a code block inside of an always false conditional based on a constant (ie. if(false) { ... or if(constant_declared_false) { ...) variable declarations of both value and reference types are compiled, but no executable code is compiled (method calls, for loops, setting the value of a variable, etc).
  3. If I set a local variable to false and test for the local variable, all code is compiled.
Rich