hash_bucket()

Conditional Attribute / Debug

Posted on: May 23, 2008

This article will introduce the Conditional Attribute and give an example of its usage. The technical level is kept low to make the text as accessible as possible. More info can be found in the official C# Programming guide, in particular the section called ‘Conditional’.

When it comes to debugging, the world (of IDEs) is full of tools to make life easier for us as developers. The latest version of Visual Studio (2008) features a vast array of built in debugging aids that help diagnose and keep track of a running application/assembly. This is all well, and maybe what I am about to say next may sound a bit old or odd, but I for one would never do away with my trusty old output console. I have talked about this before in a post that gave a brief walk through on how to open console windows from an existing and running application in Windowed mode (that is sporting one of those fancy graphical interfaces that seem to be so in fashion lately ;) ).

I have written a small dll that I hook up to must of my projects, through which you can ‘report’ debugging messages to one of 5 pre-defined ‘channels’. The report can be set to write to:

1) The Visual Studio output console (default)
2) A regular text file (you set the path)
3) A console window
4) Email
5) Wreq (my own custom project management tool)

This little tool uses reflection to keep track of what the application is up to, but you can also tell it to ‘report’ any message you choose at any time.

Eg:

DebugReporter.Report(
MessageType.Information,
“[Application Name]”,
“Creating and setting Auto Save path” +
“\nPath: ” + _path.ToString());

or:

DebugReporter.ReportMethodEnter();

DebugReporter.ReportMethodLeave();

One thing about reporting debug info this way is that when you switch to a Release build you want all of those messages to go away automatically, so that you do not have to comment out all these calls.

One way of acheiving this would be to use the #if-endif construct such as:

#if DEBUG
DebugManagers.DebugReporter.Report(
DebugManagers.MessageType.Information,
“[Application Name]”,
“Creating and setting Auto Save path” +
“\nPath: ” + _path.ToString());
#endif

This pre-processor directive would tell the compiler to skip the encapsulated block of code. However, in a typical small application I usually end up with a lot (hundreds) of calls like this and decorating them all with #if-endif just isn’t a very elegant solution. Fortunately the designers of the CLR thought about this and gave us a much better way of dealing with this situation.

One thing you can easily discern from the above code is that all these calls access the same static method on the same static class. Thus, instead of decorating all the method calls, what if we could decorate the method itself?

In .net there is a concept called Attributes that allows you to add custom behaviour and ‘properties’ to methods. The framework contains a lot of pre-defined attributes that deal with for example security, compiler-options, discoverability and much more. Also, as a developer you can define your own attributes, but that is beyond the scope of today’s topic. (See the ‘.NET Framework Developer’s Guide’, in particular the section on ‘Writing Custom Attributes’.)

One such pre-defined attributes is the ‘Conditional’ attribute. This works pretty much like an inverse version of the #if-endif construct. it tells the compiler when to, for example execute a particular method.

Note: This is not a pre-processor directive in the form we know it from of a C/C++, in fact the .net framework as no such concept since the code is JITed upon execution. Thus the above statement that the compiler executes a piece of code is sort of correct, if by compiler to mean the CLR, and by executing you mean Just-In-Time compilation… The C# Programming Guide calls this a ‘preprocessing identifier’.
(See the ms-help page ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/dv_csref/html/e1c4913b-74d0-421a-8a6d-c14b3f0e68fb.htm)

When using the Conditional attribute you define a constant condition that has to be met for any code-path that access the decorated mehod to be executed. Naturally this can help us in the debuggin scenario. One such constant that is defined automatically when building a Debug build in Visual Studio is the DEBUG constant. Thus we can do the following:

[Conditional(“DEBUG”)]
public static void Report(…)
{

}

Using this attribute is what invokes the magic. Now, if the DEBUG constant is not set, any method call to the Report method will simply be excluded from the build, keeping our Release build nice and neat and without cluttering the code with those #if-endif. In fact, the method itself wont event be present in the emitted MSIL :). That, is clean!

There are a few restrictions on using the Conditional Attribute. In particular, the method you want to decorate must have a return type of Void.

Note: This actually makes a lot of sense as the method will no longer be available and the compiler would have a hard time tracing all the possible usages of the eventual return value that might be expected by later code…

I still see a lot of (c#) code written that is full of #if-endif (almost exclusively to defer execution paths in/out of debugging), but I would highly recommend you start experimenting with using the Conditional Attribute instead (where applicable of course ;).

There are still some legitimate use for the #if-endif of course, for example when you want to skip a particular code-block within a method, or when the method you call has a return type other than Void. Thus you should not rely on the Conditional attribute to solve all of your conditional execution, but keep it around as a powerful and simple technique. Also, it might give you an excuse to learn more about the power of Attributes in .NET, and how to write your own custom Attributes.

Advertisements

4 Responses to "Conditional Attribute / Debug"

Running a client which talked to a web service I noticed:
Only the client’s System.Diagnostics.Debug.WriteLine calls were visible, not IIS’s. But when I started a Sysinternals/DebugView från another machine and connected with my dev machine the System.Diagnostics.Debug.WriteLine calls from IIS showed up in the remote machine.
So now I have a remote machine with debugoutput from my IIS and the local machine with debugoutput from the client.
I haven’t managed to get them both in the same DebugView.

Instead of writing “DEBUG” everywhere one can do:

private const string Debug = “DEBUG”;

[System.Diagnostics.Conditional(Debug)]
internal static void WriteLine(string message)…

LosManos
Thanks for pointing that out! shun the caps!! :)
Please tell me if you have any success on the above (client/server)issue.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

.

This blog has no clear focus. It has a focus though, it's just not very clear at the moment...

Dev Env.

Visual Studio 2008 Prof / NUnit / Gallio / csUnit / STools (ExactMagic) / doxygen / dxCore / TypeMock / TestDriven.net / SequenceViz / CLRProfiler / Snoop / Reflector / Mole / FxCop / Subversion / TortoiseSVN / SlikSVN / CruiseControl.net / msbuild / nant

Blog Stats

  • 81,435 hits