- If you create a new project in Visual Studio, it creates two default build configurations for you: Release mode, Debug mode.
- If you compile your project, the settings from these configurations are used to configure what the compiler does.
- In release mode, the compiled code is fully optimized, and no extra information for debugging purposes is created.
- In debug mode, there is no optimization applied, and additional information is outputted.
- When executing a release build, the compiler optimizes the code. If GC sees the object as not used, it’s no longer considered a root object and it removes it from memory.
- In debug configuration, the compiler inserts extra no-operation (NOP) instructions and branch instructions. NOP instructions are instructions that effectively don’t do anything (for example, an assignment to a variable that’s never used). A branch instruction is a piece of code that is executed conditionally (for example, when some variable is true or false).
- When the compiler sees that a certain branch is never executed, it can remove it from the compiled output. When optimizing the code, the compiler can also choose to inline short methods, effectively removing a method from the output.
- In the real world, you don’t suddenly have to start worrying about your objects being garbage collected and your code going wrong in release mode.
C# Debug vs. Release builds and debugging in Visual Studio - from novice to expert in one blog article
- Preprocessor is a program that goes through your code and applies some changes to your code before handing it off to the compiler.
- The preprocessor commands are directives to .NET compiler, specifying the sections of the code to compile or identifying how to handle specific errors and warnings within the code.
- C# does not have a specialized preprocessor, but it does support preprocessor compiler directives, which are special instructions to the compiler to help in the compilation process.
- All preprocessor directives must appear on one line. They don’t need a semicolon to indicate the end of the code.
- The most common uses of preprocessor directives are controlling when and how code is included for compiler compatibility purposes and handle differences among platforms.
- A final common use of the directives is for debugging. If you surround code with #if DEBUG, you will remove the code from a release build on most IDEs.
- The IDEs define the DEBUG symbol by default in a debug compile and RELEASE by default for release builds.
- At any given point in your source code, while the compiler is compiling that section of code, a particular conditional compilation symbol is either defined or undefined. In fact, a conditional compilation symbol is either defined or undefined–it has no value.
- A conditional compilation symbol remains defined in a source file until the end of the containing source file or until encountering an #undef directive (whichever comes first).
- All #define and #undef preprocessor directives must appear at the top of a source code file, i.e. before any valid C# tokens. The definition (or un-definition) then remains in effect until the end of the file is reached.