27

I think this is a simple question so I assume I'm missing something obvious. I don't really ever use preprocessor directives but I was looking at someone's code which did and thought it was something I should be familiar with.

So I looked at the msdn example here it has the code:

#define DEBUG
// ...
#if DEBUG
    Console.WriteLine("Debug version");
#endif

My two questions are:

  • in the example above why do they define DEBUG? I was under the impression that was set if you compile in debug v. release mode?
  • looking at the other example which has #define MYTEST and then writes to the console dependent on if it 'defined', but how does this differ from just using a variable? What am I missing here?
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
llcf
  • 271
  • 1
  • 3
  • 3

7 Answers7

20

I would actually recommend using the Conditional Attribute instead of inline #if statements.

[Conditional("DEBUG")]
private void DeleteTempProcessFiles()
{
}

Not only is this cleaner and easier to read since you don't end up having #if, #else within your code. This style is less prone to errors either during normal code edits and well as logic flow errors.

Shiv Kumar
  • 9,599
  • 2
  • 36
  • 38
  • 1
    I was unaware of this style. Thanks for posting. – Shekhar Nov 19 '10 at 06:07
  • 1
    It should be noted that the method will always be emitted regardless of whether the condition is met. The attribute only affects whether *calls to this method* will be emitted; this makes it possible to define a method in a library and give it `[Conditional("DEBUG")]` and this will affect compilation against this library. – cdhowie Jun 11 '12 at 12:44
  • Excellent, there's also more information on this over here http://stackoverflow.com/q/3788605/932917 – mstaffeld Jan 16 '14 at 16:21
  • There is an annoying about of limitations with that Attribute (no constructor (fair) but also the method must be void. – Frank V Mar 14 '14 at 15:21
9

Generally, the optional/conditional compilation symbols will be provided by the build script. It is pretty rare to see #define, except for very debug code (if you see what I mean).

Re using a variable; I often use such conditions to handle code that must run on different runtimes (mono, cf, silverlight, etc). A variable cannot suffice because the code cannot be compiled against the wrong platform (missing types/methods etc).

In the example presented I would probably just have used Debug.WriteLine; since this is decorated with [Conditional("DEBUG")], all calls to it are automatically removed if DEBUG is not defined at build.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
5

in the example above why do they define DEBUG? I was under the impression that was set if you compile in debug v. release mode?

Probably because it is example code. It is meant to demonstrate how #ifdef and friends work. I wouldn't expect you to define symbols like that in source files, unless it is for a quick test.

looking at the other example which has "#define MYTEST" and then writes to the console dependent on if it 'defined', but how does this differ from just using a variable? What am I missing here?

If MYTEST is not defined at compile time, the compiler will not actually emit the code between the #if and #endif blocks. Therefore the resultant IL will be smaller.

Also, note that these are not preprocessor directives in C#.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • 1
    [MSDN calls them "preprocessor directives"](http://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx) – Ben Voigt Nov 19 '10 at 05:37
  • But they are not. From the same article: *"the compiler does not have a separate preprocessor"*. – cdhowie Nov 19 '10 at 05:38
  • 4
    They are probably more accurately called *conditional compilation symbols*. They are similar to those found in C++, but the C# compiler does not have a separate preprocessor. (http://blogs.msdn.com/b/csharpfaq/archive/2004/03/09/86979.aspx) – Cody Gray - on strike Nov 19 '10 at 05:40
4

If you use variable all your code is compiled, when you use preprocessor directives only part of code included in executable/dll.

x2.
  • 9,554
  • 6
  • 41
  • 62
4

I would like to give one example where I have used preprocessor directive in my project.

My program creates lot of intermediate files on disk. I used #DEBUG directive to delete those files only if my project is in release mode, otherwise I keep those file so that we can view those intermediate files and determine whats happening inside.

When my app is working on production server, I build project in release mode so those files are deleted after processing is complete.

#if (DEBUG==false)
    deleteTempFiles()
#endif
Shekhar
  • 11,438
  • 36
  • 130
  • 186
  • 3
    I usually do i#f !DEBUG, I know same thing, but slightly slimmer – Neil N Nov 19 '10 at 05:59
  • @Neil, Your way is also correct but I prefer DEBUG=false because its more clear to read and understand. – Shekhar Nov 19 '10 at 06:04
  • I strongly recommend not to disable any production code in debug configurations, because it may have side effects you'll never get when debugging (yes, i know it shouldn't, but c'mon we know life, don't we?). For your example I would do it the other way round: If DEBUG is set, copy the temp files elsewhere for inspection before clobbering. Although I admit there are situations when you have to mock things (transaction services etc.). – ofi Nov 19 '10 at 07:14
2

I have some code which needs a different handling when using the Mono environment instead of the CLR - thus I have a Mono directive in some of my modules. I think this is a better example than debug

weismat
  • 7,195
  • 3
  • 43
  • 58
  • If code needs different handling, you should check whether you are running under Mono at runtime and alter behavior accordingly; that way you can still ship one binary to all platforms. (`if (Type.GetType("System.MonoType") != null) { ... }` is the recommended way to test if you are running on the Mono runtime. Note that running on Mono does not imply running on Linux; Mono is available for Windows as well as other platforms like OS X.) However, testing which runtime you are on is usually a bad idea. If you are working around a Mono bug, test if the bug itself is present instead. – cdhowie Jun 11 '12 at 12:47
1

I've used it for a lot of things. Debug messages that I only want in debug builds; clean up temp files; include diagnostic functions or actions.

Frank V
  • 25,141
  • 34
  • 106
  • 144