If you’ve programmed in C# for a while, you’ve probably stumbled upon the Conditional attribute. It allows you to specify that a certain method will only be called when a certain compilation symbol is defined. Let’s check the details of that.

The Basics

The following method is a straightforward use case for the Conditional attribute. Let’s use it to get on the same page before proceeding:

We have defined a special method here that will only be invoked when compiling the program with the DEBUG compilation symbol defined, e.g. when compiling in Debug mode. If we compile a Release build, all invocations of  Foo  will be removed entirely, leaving a zero footprint. This is quite useful for writing debug code, especially when developing a library for others to use:

Unlike an  #if  / #endif block, the Conditional attribute is not evaluated when compiling the method itself, but when compiling the method call. If we pack Foo into a library, we can build it in Release mode and still call it from a program that is compiled in Debug. It’s actually the way the System.Diagnostics.Debug class is implemented.

Conditional Attribute OR

As it turns out, you can actually define multiple Conditional attributes on the same method:

What happens is that the method will now be called when either of those compiler symbols is present. Very useful if you want to allow your users to manually activate a Debug-only diagnostic feature in Release builds for testing purposes.

Compiler Directives

You may have guessed it, but you can also fiddle with the call behavior on a per-file basis using  #define :

 Conditional Parameters

This is where it gets interesting. Of course, if you pass a primitive parameter to an omitted Conditional method, that parameter should vanish as well. But what happens when we invoke a method, query a property or create an object in order to pass the resulting value as a parameter?

Since we’re triggering state changes here, it’s not safe to omit calculating these parameters, right?

But apparently, that’s exactly what happens. This is not a quirky compiler optimization: The Conditional attribute, when inactive, acts as if the whole method call didn’t exist at all – including its arguments. I personally wouldn’t have expected this, but it makes sense when you think about it in the context of  Debug.Assert(..)  where it would be a waste of resources to calculate all the assertions despite not acting on them anyway.

Similarly, when using an anonymous delegate or lambda exclusively as parameter to an omitted Conditional method, it will be optimized away in Release builds. So even in these cases – at least as far as I observed it – there will likely be zero overhead.

Reflection

What happens when using Reflection to invoke a Conditional method?

As intuition has probably told you: It will be invoked as ordered. Nothing escapes Reflection.

Delegates

One last corner case to wrap it up:  Will a delegate of the method patch through, even if the Conditionals compiler symbol is not defined?

Nope. Because it won’t even compile. You’re not allowed to pack Conditional methods into delegates.