2012-03-22 43 views
1

有时我发现预处理程序指令对我的应用程序来说不够灵活,所以我一直在想是否有可能交换预处理程序的#if功能。if语句中的常量条件

例子:

const bool Debug = false; 
if (Debug) 
{ 
    ... 
} 

将if语句,其内容由编译删除?或者,如果Debug常数的值为true,编译器是否会删除条件检查并保留其内容?

+3

你试图看看MSIL – 2012-03-22 22:20:02

+0

下载Linqpad,你可以在2分钟内验证自己直。 – BrokenGlass 2012-03-22 22:23:20

+0

对于'const'成员,'if'语句将消失。对于静态只读成员,声明将保留。 – dlev 2012-03-22 22:25:03

回答

11

if语句及其内容是否会被编译器删除?或者,如果Debug常量的值为true,编译器是否会删除条件检查并将内容保留在原位?

是的,是的。但是,这些是实现细节,不是语言的保证。

使用if(false)控制条件编译的一些有趣的方面:​​

编译是不是条件可言; if的主体将像其他任何代码一样被编译。如果它包含语法错误,则会出现语法错误。如果它包含重载解析错误,你会得到重载解析错误。 “转到使用”和其他IDE功能继续工作。

这是从与#if false控制非常不同;由于预处理器而被忽略的文本被视为注释。 “转到使用”不会找到有条件编译的用法,您不会获得语法着色等等。但是,代码可以完全破解,因为毕竟它基本上只是一个评论。

然而,第一点是轻微的谎言;有一个区别。内部if(false)代码不检查明确分配错误:

int x; 
if (false) 
    Console.WriteLine(x); // no error! 

因为毕竟有没有办法,X向它是写在这个节目片段之前必须阅读!

3

if语句及其内容会被编译器删除吗?

是的,即使您在Debug模式下编译,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始终执行。

+0

这是真的,这也可以通过试图将黄色执行箭头拖到静态死亡分支中来看出。它不会工作(这可能是一个调试问题)。 – usr 2012-03-22 22:25:37