Jonathan Beerhalter
Jonathan Beerhalter

Reputation: 7407

Will conditionals that are always false be removed by compiler in C#

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.

Upvotes: 3

Views: 502

Answers (7)

Rich
Rich

Reputation: 36816

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.

Upvotes: 2

Dana
Dana

Reputation: 32967

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.

Upvotes: 3

lc.
lc.

Reputation: 116498

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

Upvotes: 0

Joel Martinez
Joel Martinez

Reputation: 47759

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

Upvotes: 0

Jimmy
Jimmy

Reputation: 91472

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

Upvotes: 1

Aaron Smith
Aaron Smith

Reputation: 3362

You can define your own precompiler variables.

 #define temp

 #if temp
 // Do something
 #endif

Upvotes: 1

scottm
scottm

Reputation: 28699

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
    }

Upvotes: 9

Related Questions