Preprocessor vs Conditional Compilation Attribute

Here is a little teaser program –

class Program {

#if DEBUG
   
static int test = 0;
#endif

    static void Main(string[] args) 
   
{
       
TestMethod(test); 
    }

    [Conditional(“DEBUG”)]
   
static void TestMethod(int t) { }
}

Like all questions, should this compile or not? The thing to note here is the difference in behavior between the Conditional compilation attribute and a preprocessor directive. The answer is in the documentation of the conditional attribute class.

Applying ConditionalAttribute to a method indicates to compilers that a call to the method should not be compiled into Microsoft intermediate language (MSIL) unless the conditional compilation symbol that is associated with ConditionalAttribute is defined. Applying ConditionalAttribute to an attribute indicates that the attribute should not be emitted to metadata unless the conditional compilation symbol is defined. Any arguments passed to the method or attribute are still type-checked by the compiler.

 

UPDATE to my question in the community DL by Eric Lippert

>>So this in my understanding means that unlike a preprocessor directive, happens only during translation and that means type checking and parsing etc does happen even though the method is conditional in a sense and removed only at a later stage.

Correct. If you think about it a moment you’ll see why that has to work that way. Ask yourself a few questions about how this works:

Q: How does the compiler know to remove the method? 

A: Because the method called has the conditional attribute on it.

Q: How does the compiler know that the method called has the conditional attribute on it?

A: Because overload resolution chose that method, and the metadata associated with that method has the attribute.

Q: How does the compiler know to choose that method?

A: By examining its arguments.

Therefore the arguments must be well-defined at the point of the call, even if the call is going to be removed. In fact, the call CANNOT be removed unless the arguments are there!

>>Could someone point me to which parts of the c# spec defines this behavior?

FYI, the specification begins with a handy table of contents”, which is very useful for answering such questions. The table of contents of the specification states:

2.5.1 Conditional compilation symbols

17.4.2 The Conditional attribute

So my advice would be for you to look at sections 2.5.1 and 17.4.2 if you want the specification for conditional compilation symbols vs the conditional attribute.

Cheers,

Eric