我需要在 C# 中进行一些条件编译,但也被要求保持全局符号计数低。所以不是#if ENABLE_MODULE
(并添加很多符号),我主要做 opt-out #if !DISABLE_MODULE
。
在分析核心循环时,我希望能够很好地控制关闭的内容,以便更清晰地查看结果。但即使对于空的断言调用(#if
在方法体内部),单独的调用也会花费大量时间。这就是为什么我开始使用[Conditional]
属性来完全删除调用并避免将所有内容包含在#if
降低代码可读性的部分中。
但[Conditional]
有一些警告:
- 只能一起 OR-ed。
- 否定使用 not ! 内部条件是不允许的。
- 没有办法将它们组合起来。
- 与#if 不同,它由调用者的文件范围符号定义而不是实际调用的方法文件范围符号定义来解释。
我想出了一个解决方法,但它并不漂亮并且倾向于重复代码(参见__Convoluted()
下面的方法)。禁用#if
部分中的代码被视为 Visual Studio 中的注释(因此没有名称重构),这使情况变得更糟,由于未检查所有符号组合等而变成损坏的提交。
我曾想过使用一些伞形符号,但这迫使我以正或的方式思考一切,有时我想要例如大多数断言但不从某个模块断言。
也许这有一个软件架构的答案,而不是一个实用的答案。
我正在使用 Unity,因此无法很好地控制每个配置(调试/发布/开发构建)的符号,而无需执行一些构建脚本来替换文件中的编译器参数(csc.rsp)
我的问题:有没有更好的方法来处理这个问题?
谢谢你的时间。
我做了一些功课尝试不同的选择并得出了一些结论(遵循代码)
最小测试用例 C# .NET 控制台应用程序
实用程序文件
//ENABLE is a global symbol definition at project level
#if ENABLE && EXTRA
#define _COMBINED
#endif
#if !ENABLE
#define _DISABLE
#endif
using System;
using System.Diagnostics;
public static class Utility {
[Conditional("ENABLE")]
public static void Call(string msg) {
Console.WriteLine(msg);
}
[Conditional("ENABLE"), Conditional("OTHER")]
public static void CallOr(string msg) {
Console.WriteLine(msg);
}
[Conditional("_DISABLE")]
public static void CallNot(string msg) {
Console.WriteLine(msg);
}
public static void CallNotInternal(string msg) {
CallNot(msg);
}
[Conditional("_COMBINED")]
public static void CallAnd(string msg) {
Console.WriteLine(msg);
}
public static void CallAndInternal(string msg) {
CallAnd(msg);
}
#if ENABLE //!_DISABLE
[Conditional("_NEVER")] // <-- Hack to remove MSIL call.
public static void CallNotConvoluted(string msg) { }
#else
public static void CallNotConvoluted(string msg) {
Console.WriteLine(msg);
}
#endif
#if !(ENABLE && EXTRA) //!_COMBINED
[Conditional("_NEVER")] // <-- Hack to remove MSIL call.
public static void CallAndConvoluted(string msg) { }
#else
public static void CallAndConvoluted(string msg) {
Console.WriteLine(msg);
}
#endif
}
不同的调用组合
//Works as expected
Utility.Call("Call1");
//Works as expected
Utility.CallOr("CallOr");
//Doesn't work because _DISABLE is not defined in this file
//(although it is defined at Utility)
Utility.CallNot("CallNot");
//Works because _DISABLE is defined at Utility (where CallNotInternal resides)
//BUT would have extra "empty" call
Utility.CallNotInternal("CallNotInternal");
//Doesn't work because _COMBINED is not defined in this file
//(although it is defined at Utility)
Utility.CallAnd("CallAnd");
//Works because _COMBINED is defined at Utility (where CallAndInternal resides)
//BUT would have extra "empty" call
Utility.CallAndInternal("CallAndInternal");
//Works but it seems kind of hacky/bulky
Utility.CallNotConvoluted("CallNotConvoluted");
//Works but it seems kind of hacky/bulky
Utility.CallAndConvoluted("CallAndConvoluted");
当全局符号设置以下时,代码输出。请注意CallAnd
并CallNot
表明 Conditional 不像 #if 那样工作。
ENABLE and EXTRA
----------------
Call1
CallOr
CallAndInternal
CallAndConvoluted
ENABLE
-----
Call1
CallOr
(no symbols)
------------
CallNotInternal
CallNotConvoluted