Geeks With Blogs

News Google

Nick Harrison Blog<Nick>.Next()

ConditionalAttribute

Certain methods especially in the System.Diagnostics namespace are decorated with ConditionalAttributes similar to this:

[Conditional("DEBUG")]

What is this all about?  The conditional attribute provides a nice way to have code be conditionally ignored.  Methods decorated with this attribute will not have their calls compiled to IL unless the condition is true.

In the attribute shown above, any calls to the method will not be made unless the symbol DEBUG is defined.

This creates some very intriguing possibilities.  Some of which might be nice and some of which might be pure evil.

Code like this:

#define TEST
using System;
public class MyClass
{                
   public static void Main()
   {
      #if (TEST)
         Console.WriteLine("TEST is defined");      
      #endif
   }
}


Can be rewritten to code like this:

 

    #define TEST
    public class MyClass
    {

        public static void Main()
        {
            TestWriteLine("Test is defined");
        }

        [System.Diagnostics.Conditional("TEST")]
        public static void TestWriteLine(string message)
        {
            Console.WriteLine(message);
        }
   }
Is this better?   Consider this, you would have to wrap every method call the “if test compiler directives” to achieve the same effect of adding the attribute to one place.

If you are only calling the method from one place, this probably doesn’t matter, but if you are potentially calling this method from throughout multiple enterprise applications, this is unrealistic.

The compiler directives can cause confusion by interrupt the logic flow.  

Here are some examples where this might be very useful and practical

Suppose you wanted to be able to support a build that could be used for code coverage testing without having to change code for a production build.

Suppose you wanted to have a build to support performance metrics without having to change any code.

Suppose you wanted to have a build to support debugging information without having to change production code.

Turns out, this last example is the whole reason this attribute was created.   This is how Debug.WriteLine works.    

Try this, sprinkle your code with calls System.Diagnostics.Debug.WriteLine(),  compile in debug mode, and examine the assembly with Reflector.   You will notice that all of your calls to WriteLine are there.   Now compile in release mode and examine the assembly with Reflector.   You didn’t change any code, but now none of the WriteLine statements are there.

We could create a method decorated with a conditional attribute requiring that the symbol CodeCoverage must be defined and then call this method at the start of every function.   Compile the code defining this symbol.   Now when we run through a round of testing, we will get a list of every method that was called.    Recompile the code without defining this symbol and the overhead of logging function calls goes away.

As is often the case, there are a couple of caveats.  This is not documented on MSDN anywhere that I have seen.   Any method decorated with this attribute must return void and cannot have output parameters.  This is intended to prevent the removal of this code from causing any unintended side effects.  You would not want to rely on a variable being initialized by a function that may or may not be called.  

How could you envision using such attributes?  

 

 
Posted on Tuesday, February 19, 2008 8:56 PM | Back to top


Comments on this post: Conditional Attribute

comments powered by Disqus

Copyright © Nick Harrison | Powered by: GeeksWithBlogs.net