我尝试在C#中使用简单的预处理程序指令进行调试和发布模式。
例如:
using System;
public class C {
public void M() {
#if DEBUG
Console.WriteLine("Debug");
#else
Console.WriteLine("Release");
#endif
}
}
这段代码非常简单明了。
但是当我看到IL代码时,我没有关于debug指令的任何内容。
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit C
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig
instance void M () cil managed
{
// Method begins at RVA 0x2050
// Code size 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Release"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method C::M
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x205e
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method C::.ctor
} // end of class C
这对我很有意思,为什么会这样。
我的意思是为什么我在IL代码中没有看到任何有关DEBUG模式的内容?
P.S。我使用sharplab来查看IL代码。
P.S.2 live example
答案 0 :(得分:6)
这是因为编译器使用预处理程序指令根据配置生成不同的IL代码。它不被CLR使用。
至于为什么SharpLab没有做正确的事情,它使用Rosyln并且只设置优化设置。它没有设置预处理器变量。
public void SetOptimize([NotNull] IWorkSession session, [NotNull] string optimize) {
var project = session.Roslyn.Project;
var options = ((CSharpCompilationOptions)project.CompilationOptions);
session.Roslyn.Project = project.WithCompilationOptions(
options.WithOptimizationLevel(optimize == Optimize.Debug ? OptimizationLevel.Debug : OptimizationLevel.Release)
);
}
我建议您向SharpLab提出一个问题,即他们会按预期实现此功能。
答案 1 :(得分:2)
有两个概念让您感到困惑。
发布/调试编译模式:
它控制编译器是否在代码中发出调试信息(例如NOP
设置断点的指令)以及其他一些方面,例如在编译器和JIT级别上执行的优化。这基于C#编译器的/debug
参数。
预处理程序符号:
它控制为编译运行定义的符号。默认情况下,在使用Visual Studio创建C#项目时,这些在调试模式下设置为DEBUG
和TRACE
,在发布模式下设置为TRACE
。然后,这些符号用于解析您正在使用的#if
指令。这基于C#编译器的/define
参数
在您的情况下似乎正在发生的事情是,您的工具告诉C#编译器在调试/发布模式下运行但是不在参数中提供预期的预处理器符号(DEBUG
)。因此,您会在Release和Debug配置中看到非DEBUG
代码。