首页 > 解决方案 > 基于常量的条件编译?

问题描述

是否可以根据类中定义的一些常量值有条件地编译类和方法,例如我想要这样的东西。

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
}

显然我知道一般情况下 C# 是如何完成条件编译的,我想根据类中的常量值进行条件编译,而不是基于预处理器定义。知道很多编译时的东西都适用于常量(例如 Guid 属性),有没有办法根据类常量有条件地编译方法/类?有一个 Conditional 属性,但它似乎也只适用于定义。

我有一个具有多种构建模式的复杂项目,我想让其他人更容易构建我的项目。例如,我需要在一个设置上拥有 3 种不同的模式(可能更多),在另一种设置上拥有 2-3 种不同的模式。所以为了让其他人更容易编译我的项目,我需要有 3 * 3 = 9 个不同的预处理器定义和 9 个不同的 csproj 文件。如果我需要添加更多设置/模式/常量,这个故事并不能真正扩展。对于将编译我的代码但以前从未见过的人来说,这可能会变得非常混乱。至少使用常量编译器会对它进行类型检查,因此搞砸的可能性较小。

显然,我可以构建代码来支持所有配置常量的变体,并在运行时基于它们调用代码,但我想进行优化,以便不会编译未使用的代码。

标签: c#.net

解决方案


不 -

C# 不会评估#if预处理器指令中的表达式- 它只查看符号是否已定义:

当 C# 编译器遇到一个#if指令,最后是一个#endif指令时,它仅在定义了指定符号的情况下编译指令之间的代码。与 C 和 C++ 不同,您不能将数值分配给符号。C# 中的#if 语句是布尔值,仅测试符号是否已定义。

(重点补充)

所以做你想做的事情的正确方法是:

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
}

符号可以在该代码文件中定义,也可以通过 CSC.EXE 的命令行参数定义。


推荐阅读