1
votes

Is it possible to conditionally compile classes and methods based on some constant value defined in a class, for example I'd like to have something like that.

public enum BuildMode : int {
    One = 1,
    Two = 2,
    Three = 3
}

public class BuildConfig {
    // I will change this line, based on what build I want
    public const BuildMode Mode = BuildMode.One;
}

public class SomeClass {
   #if BuildConfig.Mode == BuildMode.One
       public void SomeMethod() { /* Implementation one */ }
   #elif BuildConfig.Mode == BuildMode.Two
       public void SomeMethod() { /* Implementation two */ }
   #elif BuildConfig.Mode == BuildMode.Three
       public void SomeMethod() { /* Implementation three */ }
   #endif
}

Obviously I know how condition compilation is done in C# in general, I want to make conditional compilation based on constant value in a class, not based on preprocessor define. Knowing that a lot of compile time stuff works with constants (like Guid attributes for example), is there a way to conditionally compile methods/classes based on class constants? There is a Conditional attribute, but it seems that it only works with defines as well.

I'm having a complex project with multiple build modes and I want to make it easier for other people to build my project. For example, I need to have like 3 different modes (potentially more) on one setting and like 2-3 different modes on the other setting. So to make it easier for other people to compile my project I will need to have like 3 * 3 = 9 different preprocessor defines and 9 different csproj files. And this story doesn't really scale if I will need add some more settings/modes/constants. And it can become really messy for a the person who will compile my code, but haven't seen it before. At least with the constants compiler will type check it, so there are less possibilities to mess things up.

Obviously I could build code to support all variants of configuration constants and call the code based on them at runtime, but I want to make optimization so that unused code won't be compiled in.

1
Good question. I don't think it's possible. It might help if you add to your question why you want to avoid "classic" conditional compilation (i.e., by defining your constant as a preprocessor define), so that people can suggest alternative solutions to your underlying problem. - Heinzi
I think preprocessing is done before the compilation and const info is present during compilation. so it wont be possible. lets wait for experts answers - vivek nuna
@Heinzi good suggestion - vivek nuna
@Heinzi, added some clarification. - Leff Ivanov

1 Answers

1
votes

No -

C# does not evaluate expressions in the #if preprocessor directive - it only looks to see if the symbol is defined :

When the C# compiler encounters an #if directive, followed eventually by an #endif directive, it compiles the code between the directives only if the specified symbol is defined. Unlike C and C++, you cannot assign a numeric value to a symbol. The #if statement in C# is Boolean and only tests whether the symbol has been defined or not.

(emphasis added)

So the proper way to do what you want is to do:

public class SomeClass {
   #if BUILD_MODE_ONE
       public void SomeMethod() { /* Implementation one */ }
   #elif BUILD_MODE_TWO
       public void SomeMethod() { /* Implementation two */ }
   #elif BUILD_MODE_THREE
       public void SomeMethod() { /* Implementation three */ }
   #endif
}

Where the symbol could either be defined in that code file or via command-line parameters to CSC.EXE.