12

Is it possible to create a method which performs debugging assistance like the System.Diagnostics.Debug class?

I'm looking for a way to construct a method which when called by an assembly compiled with the DEBUG conditional compilation symbol defined, results in an operation, and which is a no-op when called by an assembly without the symbol defined.

If possible, I'd like it to be possible for the calls to the debugging methods to add minimal overhead or increase in size to the release version of the assembly.

To clarify, the debugging methods should be in an assembly compiled in Release mode. Calls to the methods should only generate operations when called from an assembly with the DEBUG symbol defined in the scope of the method call.

5 Answers 5

36

Add the Conditional attribute to the method, like this:

[Conditional("DEBUG")]
public void Whatever() {
    //...
}

Note that the method must return void, and cannot have any out parameters; otherwise, it would be impossible to remove a call to it.

The method will be compiled into the assembly, but CLS-compliant compilers will only emit calls to the method if the assemblies that they are compiling has DEBUG defined. Note that the C++ compiler is not CLS-compliant and will always emit the call.

Sign up to request clarification or add additional context in comments.

5 Comments

+1 for pointing out that Conditional it's not foolproof (does that mean it's even CLI-compliant?) What happens for C++ calls to Debug.WriteLine? Is that for all versions? It/d be nice to have you edit that in :P
I haven't actually tried it. The MSDN page on ConditionalAttribute just says that the C++ compiler isn't compliant, without saying which versions.
As I stated in the answer (and will always emit the call), the C++ compiler (I believe) will always emit calls to WriteLine, even in Release.
I would think that non-void or "with out params" methods should be a compile error if the ConditionalAttribute is applied.
It is: error CS0578: The Conditional attribute is not valid on '...' because its return type is not void
6

ConditionalAttribute

BTW the code for the method being called remains in the assembly -- it's the calls to it that are removed at compilation time

Bonus topical blog post: http://blogs.msdn.com/ericlippert/archive/2009/09/10/what-s-the-difference-between-conditional-compilation-and-the-conditional-attribute.aspx

Comments

3

If you disassemble System.Diagnostics.Debug class using Reflector you can see that this is done using the [Conditional("DEBUG")] attribute:

public sealed class Debug
{
    private Debug();
    [Conditional("DEBUG")]
    public static void Assert(bool condition);
    // etc...
}

Comments

1

If you need another signature than void func(..) without out parameters, what would be wrong with

MyDebugObject Foo(out int justForGrins)
{
    justForGrins = <safe value for release builds>;
    MyDebugObject result = <safe value for release builds>;
    #if DEBUG
     .. run code you need for your debugging...
    #endif
     return result;
}

It is more verbose and less elegant than the ConditionalAttribute, but it would allow you a more flexible signature.

Comments

0

Why not try something like this ?

#if DEBUG
        private void DebugLog(string message)
        {
            // do whatever u want.
        }
#endif

2 Comments

This creates a problem where the method does not exist when compiling under a non-debug build. Any code trying to call this method would then not compile. The Debug class has methods which you can call from debug code, but to which the calls are removed when compiling release code.
@Tragedian Even with the issues you mention this can be a superior solution in some circumstances. This is a valid answer as long as what you mentioned is taken into account.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.