有时我发现预处理程序指令对我的应用程序来说不够灵活,所以我一直想知道是否可以交换预处理器的#if
功能。
示例:
const bool Debug = false;
if (Debug)
{
...
}
编译器会删除if语句及其内容吗?或者,如果Debug
常量的值为true
,编译器是否会删除条件检查并保留内容?
答案 0 :(得分:11)
编译器会删除if语句及其内容吗?或者,如果Debug常量的值为true,编译器是否会删除条件检查并保留内容?
是的,是的。但是,这些是实现细节,而不是语言的保证。
使用if(false)
控制条件编译的一些有趣方面:
编译根本没有条件; if
的主体将像任何其他代码一样进行编译。如果它包含语法错误,您将收到语法错误。如果它包含重载解析错误,您将获得重载解析错误。 “转到使用”,其他IDE功能继续有效。
这与使用#if false
控制非常不同;由于预处理程序而被省略的文本被视为注释。 “转到用法”将找不到有条件编译的用法,您不会获得语法着色,等等。但是,代码可以完全破解,因为毕竟它基本上只是一个注释。
然而,第一点是轻微的谎言;有一点不同。未检查if(false)
内的代码是否存在明确的分配错误:
int x;
if (false)
Console.WriteLine(x); // no error!
因为毕竟,在用这个程序片段写入之前,x是无法读取的!
答案 1 :(得分:3)
编译器会删除if语句及其内容吗?
是的,即使您在调试模式下编译,if
语句也将从生成的IL中删除。
或者,如果Debug常量的值为true,那么 编译器删除条件检查并保留内容?
是的,即使你在调试模式下编译也会发生这种情况。
例如:
static void Main()
{
const bool Debug = false;
if (Debug)
{
Console.WriteLine("ok");
}
}
产生以下IL:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 8
L_0000: ret
}
正如您所看到的,该方法的整个主体已从IL中删除
和
static void Main()
{
const bool Debug = true;
if (Debug)
{
Console.WriteLine("ok");
}
}
结果:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 8
L_0000: ldstr "ok"
L_0005: call void [mscorlib]System.Console::WriteLine(string)
L_000a: ret
}
此处始终执行Console.WriteLine而不执行任何if
。