devoured elysium
devoured elysium

Reputation: 105037

Conditional("Debug") + #if DEBUG

I have seen in Debugging .net 2.0 Applications the following code

[Conditional("DEBUG")]
void AssertTableExists() {
    #if DEBUG
        ...
    #endif
}

Is there any reason to use the #if directive? I mean, from what I understand the method will only be called if the DEBUG is defined, so I don't see a point in having the #if in the method body.

Upvotes: 8

Views: 3452

Answers (2)

Eric Lippert
Eric Lippert

Reputation: 659994

Coincidentally I just happened to answer your question on my blog last week.

http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/

The #if directive is necessary if the body of the method refers to entities which are themselves declared under #if DEBUG directives. For example

#if DEBUG
static private int testCounter = 1;
#endif

[Conditional("DEBUG")] void CheckConsistency()
{
#if DEBUG
  testCounter++;
#endif
...

That would not compile in the release build if you omitted the #if DEBUG in the method body.

Upvotes: 20

Konstantin Spirin
Konstantin Spirin

Reputation: 21271

Actually there are a lot of differences. ConditionalAttribute looks cleaner in code but it has a lot of limitations and at least one advantage over #if.

  • #if completely removes code from compilation if symbol is not defined.

  • #if gives you better control over granularity - you can surround one line inside a method or whole method or certain members of a class of even whole class.

  • #if allows you to write complex conditions like this:

    #if DEBUG & !NO_NETWORK
    
  • #if has #else and #elif to allow more complex scenarios.

  • [Conditional] is only applicable to a single whole method returning void.

  • [Conditional] includes code into compiled assembly but removes all calls to it. If somebody references your assembly, he would see methods marked with [Conditional] and would be able to use them - this is something you can't achieve with #if.

It's interesting to open .Net Framework assemblies with reflector, find methods marked as Conditional["DBG"] and see their usage. None of them, even internal ones, are used anywhere! That's because Microsoft compiled .Net for release without symbol "DBG" defined but they were actually using those methods to debug .Net during development.

  • It's not possible to have two method with the same signatures marked with [Conditional] but you can achieve it with #if.

As a last note I must say that conditional compilation sometimes plays evil games when you get completely different behavior in debug and release versions and you only find out about it after you deploy your code and users start complaining. So as a rule of thumb, try to avoid changing behavior with #if, use it only to change input data.

Here's an example of using #if - different application configuration for debug and release versions.

static string ConnectionString
{
#if DEBUG
    get { return "<debug connection string>"; }
#else
    get { return "<release connection string>"; }
#endif
}

Upvotes: 10

Related Questions