In this post let’s see the use of Conditional attribute and how it differs from #if directive.
It’s always best to go by an example. Consider the following.
It’s more than simple. If we run this “Hello World 1” will be printed on console. Now imagine that I want the method to be run only when a given condition satisfies. I know you can think of variety of ways to achieve that. But here the condition is based on a compilation symbol (DEBUG etc.).
Now let’s modify the code adding a compilation symbol named SOMETHING.
Now if we run this application, again "Hello World 1" will be printed on the console. And if we commented out the first line "#define SOMETHING", SayHello1() method will not get called thus the application will not print anything. It’s basically because the condition fails.
Now as you might aware, I can do the same using #if directive. Let’s modify the code to use #if.
This will print “Hello World 1” and if we commented out the SOMETHING symbol, SayHello1() method will not get called. It’s basically Just as in Example 2. So now you must be wondering what’s the difference between Conditional attribute and #if directive. Let’s move on.
The first difference is, when you use #if, the code which is wrapped between #if and #endif, will only get compiled if the condition next to #if is true. Basically you can write almost anything within the #if and #endif and as long the condition is false, it will not throw any compilation errors (even if there are any).
The second and most important difference is, how IL is emitted in both these scenarios. When you use #if, the IL for code within the #if and #endif, will only get emitted if the given condition is true. Where as when you use Conditional attribute, IL will be emitted based on the method calls. Confused?, let’s go by the example. Let me modify the code to use both Conditional attribute and #if, and then let’s compare the IL which gets generated.
Now after compiling the code, let’s see what the generated IL is (here I am using ildasm.exe).
Here let’s see what we have for Main() method.
|IL for Main()|
You can see that IL is generated for two method calls SayHello1() and SayHello2(). Now let’s commented out the compilation symbol SOMETHING, compile the code and examine the emitted IL back again.
|IL for Main()|
Now there is nothing on SayHello1() and SayHello2() method calls in Main() method. Still no difference. Let’s come to this later in the post again.
Now let’s modify the code further as below.
Take a note that, I have the first line commented out (otherwise, there won’t be any difference). Now let’s compile and examine the IL on Main() method back again.
|IL for Main()|
And now, you should be able to see a clear difference. There is nothing on SayHello1() method call, but you can see the IL code for SayHello2() method call.
The reason is, now the call to our conditional method (SayHello3()) is done through intermediate method (SayHello2()). And you can see, even if I use the same approach in #if scenario, but still no IL was generated for that.
And now the reason for IL code to be same on Example 4 is, in that case we were directly calling a conditional method (SayHello2()) from the Main() method. And since the condition is false, compiler knows it can’t call the SayHello2(). Because of that no IL code is generated for conditional (SayHello2()) method call.
Hope this post gives you a clear understanding on Compilation attribute and it’s difference between #if directive.