Question on Item 4
MSDN uses a different idiom to support multiple conditions on an attribute. I think it has a number of shortcomings.

Question: Marc Jennings writes:

In the section on Conditionals you say that in order to create a method that will fire if more than one condition is true (logical AND), you need to use

#if (VAR1 && VAR2)
#define BOTH
#endif

However, it is possible to chain the conditionals together (according to MSDN, anyway…)

<QUOTE from=”MSDN”>

[Conditional("A")] public static void IfAandB( )
{
   AandBPrivate( );
}

[Conditional("B")] static void AandBPrivate( )
{
   /* Code to execute when both A and B are defined... */
}

Call IfAandB; if both A and B are defined, AandBPrivate will execute.

</QUOTE>

Is there any reason to use your method above the MS one? 

Answer:

I chose using the #if logic over chaining conditionals because it produces code that is much easier to maintain.

Using the idiom I preferred, the MSDN sample would look like this:

#if (A && B)
#define BOTH
#endif

[Conditional("BOTH")] static void AandBPrivate( )
{
   /* Code to execute when both A and B are defined... */
}
I look at the top of the file to find any defined environment variables. And, the single environment variable used to control the compilation of a function is found on the method in question. The sample from MSDN can be perverted in a couple ways. First, I can easily circumvent the first check:

/* No conditional attribute */ static void BPrivate( )
{
   AandBPrivate( );
}

The code inside AandBPrivate() can be accessed when only B is defined. That certainly looks like it was not intended.

The MSDN idiom does not scale well either. Putting the Boolean logic in the conditional, I can easily create more complicated expressions:

#if (A && B && C && D)
#define ALL

#endif

To do the same thing following the MSDN idiom requires this:

[Conditional("A")] public static void IfAandB( )
{
   AandBPrivate( );
}

[Conditional("B")] static void AandBPrivate( )
{
   AandBAndCPrivate( );
}

[Conditional("C
")] static void AandBandCPrivate( )
{
   AandBAndCandDPrivate( );
}

[Conditional("D
")] static void AandBandCandDPrivate( )
{
   AandBAndCandDPrivate( );
}

It gets maddening fairly quickly.

Finally, putting the conditionals at the top of the file means I can add methods that are dependent on the absence of an environment variable, which is not supported by the conditional attribute:

#if ( ! D )
#define NotD

#endif

[Conditional("NotD")] static void NotDPrivate( )
{
/* contents elided. */

}



Published Tue, Jan 11 2005 6:56 PM by wwagner
Filed under:

Leave a Comment

(required) 
(required) 
(optional)
(required)