C# Compiler Directives - c#

I’m looking at some C# code, and have come across the following statement:
#if DEBUG
// Do something here
#else
// Do something else
#endif
I assumed that DEBUG would be a defined somewhere as follows:
#define DEBUG
But I’m unable to find such a definition, although the code seems to behave as though it were set. Is DEBUG a special case, and if so, how is it set / unset?

On the project, go to Properties -> Build. Under general, you have an option there for defining both DEBUG and TRACE.

It is set with the #define directive or in the compiler settings. It is common for DEBUG to be defined in debug releases, so you could conditionally compile some code like in your example.
You can read more about it on MSDN.

If you look in the project properties you will find a debug option DEBUG
Then you can do in C#:
[Conditional("Debug")]
public void DebugThis()
{
}

You can also define the DEBUG and TRACE conditional compilation constants under the project Properties' Build tab. For this instance, Define DEBUG constant checkbox is probably checked for your project.
More details # MSDN.

Related

What is "#if" directive used for in c# and what "symbols" stand for?

I'm trying to understand how #if statement works on C# and how it is used.
After reading some documentation, I have got to the conclusion that it is used to compile the code in it if the "symbol" in the condition is defined.
#if DEBUG
Console.WriteLine("Debug version");
#endif
The problem here is that I don't know what they mean by "symbol" (in this case, DEBUG), and I'm struggling to find an answer due to the wide meaning of this word.
What are these "symbols" and what is the purpose of these "preprocessor directives"?
As folks already said, it is a pre-processor directive. Code inside the #if DEBUG ... #endif will get conditionally compiled, depending on whether the symbol DEBUG is defined.
In this case, DEBUG is simply a symbolic name introduced specifically for the pre-processor so that it can distinguish blocks of code that should or should not be compiled.
You can define a new pre-processor symbol in the project settings:
Here, we have a total of four symbols defined:
DEBUG
TRACE
ANOTHER_SYMBOL
YET_ANOTHER_SYMBOL
DEBUG and TRACE are kind of special because they are so widespread. This is why they have dedicated checkboxes. The term "constant" here is used interchangeably with the term "symbol". However, I hear "symbol" more frequently in this particular context.
Another way to define a symbol is through code. You can add #define directives at the very beginning of your .cs source files:
#define YET_ANOTHER_SYMBOL
Those are PreProcessor Directives. In your case, it will check if the DEBUG symbol is defined saying #define DEBUG then the piece of code Console.WriteLine will gets executed
#if DEBUG
Console.WriteLine("Debug version");
#endif
As you already assumed the DEBUG-symbol is used by the compiler in order to either translate the code or not. So in a release-build - where DEBUG doesn´t exist - the code is not compiled into IL.
A symbol here means a variable introduced to the compiler. Those are defined in VS Project Properties-->Build-->conditional complation symbols. However there exists a set of pre-defined symbols - such as DEBUG.
In addition to the predefined, you can also define your own conditional compilation symbol either at the file-level or the project level:
https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.conditionalattribute?redirectedfrom=MSDN&view=netframework-4.7.2
e.g, type this at the start of the file to define "CONDITION1"
#define CONDITION1
or define them under the project properties-->build-->Conditional compilation symbols.
Here you can also see the "debug" and "trace" constants predefined (if checked for your config).
"Symbols" in this context means identifiers that are called "conditional compilation symbols" and are only useful for the #if directive.
You can set them:
In VS from Project properties->build->conditional compilation symbols (as #HimBromBreere wrote) note that there are checkboxes for the commonly used DEBUG and TRACE symbols
From the compiler command line with the -define option
In the code with the #define directive

Enable code on Release compilation

I have code which I would like to enable for compilation when I build project using Release configuration and disable while debugging. How to do what?
Use a preprocessor directive.
#IF ! DEBUG
//Your code here
#ENDIF
Though, if your code is full of these, you may want to consider other options, such as
Another alternative is to use the ConditionalAttribute on a method so it will only be used if a specific symbol has been defined:
[Conditional("RELEASE")]
public void MyReleaseMethod()
{
}
Use a preprocessor directive. Surround the code with:
#if !DEBUG
// Release-only code goes here...
#endif
In the standard debug and release configurations in Visual Studio, the DEBUG symbol is defined when compiling in debug and not in release, so code in between the two directives above will only be compiled in release mode.
If you need to do one thing in debug and another thing in release, you can do this:
#if DEBUG
// Debug-only code goes here...
#else
// Release-only code goes here...
#endif
See the C# preprocessor documentation for more details.

When to use preprocessor directives in .net?

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?
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.
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.
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#.
If you use variable all your code is compiled, when you use preprocessor directives only part of code included in executable/dll.
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
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
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.

C# how can I use #if to have different compile result for debug and release?

In C++ we can use #ifdef to eliminate some debug statements when we release. C# is different from C++ in preprocessor. Can I still get the same result useing C# #if. We want to eliminate ALL debug statements by change one place and we have several different types of debug statements. Can have one file which contains ALL our #ifdef flags to turn on or turn off those debug statements? thanks
You can wrap code in:
#if DEBUG
// debug only code
#endif
However, I don't recommend this. It's often a better alternative to just make a method and flag it with the [Conditional("DEBUG")] attribute. See Conditional on MSDN for more details. This allows you to make debug only methods:
[Conditional("DEBUG")]
public void DebugPrint(string output) { // ...
}
Then, you can call this normally:
DebugPrint("Some message"); // This will be completely eliminated in release mode
Use something like:
#if DEBUG
System.Console.WriteLine("This is debug line");
#endif
The according the MSDN docs
The scope of a symbol created by using #define is the file in which it was defined.
So you can't have a file that defines several other defines that are used throughout your program. The easiest way to do this would be to have different configurations on your project file and specifying the list of defines for each configuration on the command line to the compiler.
Update:
You can set your project defines in Visual Studio by right-clicking on your project and selecting Properties. Then select the Build tab. Under general you can specify the defines to be sent to the compiler under "Conditional compilation symbols". You can define different project settings using the Configuration Manager (Build->Configuration Manager)
Update 2:
When the "Conditional compilation symbols" are specified, Visual Studio emits a /define on the command line for the compiler (csc.exe for C#), you can see this by examining the output window when building your project. From the MSDN docs for csc.exe
The /define option has the same effect
as using a #define preprocessor
directive except that the compiler
option is in effect for all files in
the project. A symbol remains defined
in a source file until an #undef
directive in the source file removes
the definition. When you use the
/define option, an #undef directive in
one file has no effect on other source
code files in the project.
You can use symbols created by this
option with #if, #else, #elif, and
#endif to compile source files conditionally.

Can I prevent the CLR from optimizing away debugging information?

I've written an abstract base class for unit tests that sets up just enough environment for our tests to run. The class exposes some of the runtime environment bits as properties whose types vary test by test (the property types are type arguments specified in the inheriting, concrete test class).
This is all well and good, except a co-worker noticed that he can't view any of the class' properties in the debugger. Turns out the reason is that he had no fields defined in his inheriting class, and the CLR optimized something or other away, so the debugger couldn't display the properties. Is it possible to prevent this in the base class somehow, or do I have to resort to telling everyone they need to define at least one field which is used somewhere during the tests?
Edit:
Sounds like a likely culprit should be the optimization/debug settings. That said, I'm building the app from Visual Studio in Debug mode, I've double-checked that all projects are set for a debug build, and none of the projects in this solution have the Optimize flag set.
Perhaps it would also be relevant to note that I'm using MSTest and the Visual Studio test runner.
Edit 2:
By "can't view properties" I'm referring to when I evaluate the property in Quickwatch and get a red exclamation mark and a text "Could not evaluate expression" error text. And lest you think I'm entirely off base with my suspicions, adding an instance field that gets initialized in the test initialize method makes the problem go away...
Edit 3:
Checked the build output. I notice that the compiler is invoked with these options:
/debug+
/debug:full
/optimize-
/define:DEBUG,TRACE
I should think that would be enough to stop this from happening, but there you go. :)
I've encountered this same problem before, and it's invariably due to the fact that Debug mode has been turned off in some way. Try checking each of the following:
The current build configuration for the solution and the appropiate project(s) is Debug.
In the Build tab of the property pages, the Optimize code checkbox is unchecked.
If this is all correct, then I recommend you paste the text written to the Output window here so can we can potentially spot any more unusual cause of the issue.
Make sure your arent trying to debug your release build.
All of these compile settings set behind these configurations.
The debug version is one for debugging ;-)
In my case, the project configuration was correct, but my code was the result of a decompilation from ILSpy, and it had assembly attributes like the following:
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
Removing these attributes fixed the debugger...

Categories

Resources