Alternatives to Conditional Compilation in C#
Asked Answered
F

7

15

What is the alternative to having code with conditional compilation in C#?

I have a class that has lots of code that is based on # ifdef .. After sometime my code is unreadable.

Looking for refactoring techniques to use for better readability and maintenance of code with many #if defs

Flowerer answered 24/9, 2010 at 12:1 Comment(1)
Why do you need it in the first place? Is it regarding debug info?Fresher
P
27

One thing is to use the ConditionalAttribute:

[Conditional("DEBUG")]
public void Foo()
{
    // Stuff
}

// This call will only be compiled into the code if the DEBUG symbol is defined
Foo();

It's still conditional compilation, but based on attributes rather than #ifdef, which makes it generally simpler.

Another alternative is simply to use Boolean values at execution time, instead of doing it all at compile time. If you could give us more details of what you're trying to achieve and how you're using conditional compilation, that would be useful.

Phonate answered 24/9, 2010 at 12:4 Comment(2)
In the case of debug prints that take strings as arguments, those strings can still be interned into the program's executable despite none of the parameters ever being evaluated. Do you know of a way to get the same results as C++'s "#define DebugPrint ((void)0)" from within C#?Unbiased
@Blake: Have you validated that that is true? I wouldn't expect it to be, though I may be wrong.Phonate
S
9

An alternative is to use the ConditionalAttribute. The conditional attribute works in a similar way.

#define TRACE_ON
using System;
using System.Diagnostics;

public class Trace 
{
    [Conditional("TRACE_ON")]
    public static void Msg(string msg)
    {
        Console.WriteLine(msg);
    }
}  

public class ProgramClass
{
    static void Main()
    {
        Trace.Msg("Now in Main...");
        Console.WriteLine("Done.");
    }
}
Slyviasm answered 24/9, 2010 at 12:7 Comment(0)
L
6

If it's a code-readability issue, you might consider using .Net's partial class qualifier and put the conditional code in separate files, so maybe you could have something like this...

foo.cs:

public partial class Foo
{
    // Shared Behavior
}

foo.Debug.cs:

#if DEBUG
public partial class Foo
{
    // debug Behavior
}
#endif

foo.bar.cs:

#define BAR
#if BAR
public partial class Foo
{
    // special "BAR" Behavior
}
#endif

I'm not sure whether or not you can define your conditionals outside of the code file though, so doing something like this might reduce the flexibility of the conditional definitions (e.g. you might not be able to create a conditional branch against BAR in, say, the main file, and having to maintain multiple defined BARs could get ugly) as well as require a certain dilligence to go to the files to effectively enable/disable that bit of code.

So, using this approach might end up introducing more complications than it solves, but, depending on your code, maybe it could be helpful?

Loquacity answered 24/9, 2010 at 13:29 Comment(0)
F
1

Using ConditionalAttribute would be a start. Otherwise, quite a bit of what folks often do with conditional compilation can usually be handled by inversion of control and/or judicious use of factories.

Frigorific answered 24/9, 2010 at 12:5 Comment(0)
C
1

Polymorphism.

Approach it the same way as you would any spaghetti code with lots of conditional branches on the same condition.

Abstract out the differences into a base class or interface.

Construct the concrete class depending on build (one #if). Pass the concrete object to your App, and then your app calls the methods defined on the interface.

Constantino answered 24/9, 2010 at 12:7 Comment(0)
M
0

IF the reason you are using conditional compilation can be easily refactored, you might consider using the Managed Extensibility Framework to load the code dynamically based on conditions at runtime.

Muse answered 24/9, 2010 at 13:36 Comment(0)
D
0

Expanding on Jon's answer, while there a number of limitations on using the ConditionalAttribute, there is a significant advantage. When the condition is false, the calls to conditional method are omitted. For example, you can add 100's of calls to a logging system, say for debugging, that can be conditionally excluded from the production code. When they are excluded, there is no overhead associated with calling a method which does not need to be called. Using #ifdef, you would have to wrap every call to the logging system to conditionally exclude them.

Note this only works across assemblies, if the caller of the conditional method is re-compiled.

Doane answered 12/4, 2014 at 22:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.