【问题标题】:C# Preprocessor Directives in the IL codeIL 代码中的 C# 预处理器指令
【发布时间】:2017-08-15 11:42:41
【问题描述】:

我尝试在 C# 中使用简单的预处理器指令进行调试和发布模式。

例如:

using System;
public class C {
    public void M() {
        #if DEBUG
            Console.WriteLine("Debug");
        #else
            Console.WriteLine("Release");
        #endif
    }
}

这段代码非常简单明了。

但是当我查看 IL 代码时,我没有任何关于调试指令的信息。

.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 模式的信息?

附:我使用 sharplab 查看 IL 代码。

P.S.2 直播example

【问题讨论】:

  • 您是否查看了用于调试配置的 IL?
  • @GalacticCowboy 不,我在寻找 DEBUG 配置
  • 您展示的是 Release IL。 Debug IL 看起来不一样。
  • @TarasKovalenko 使用 Visual Studio 和 msbuild 进行调试时会发生 2 件不同的事情:1. 设置了 DEBUG 变量,2. 告诉编译器优化代码....也许是该 sharplab 示例没有设置DEBUG 标志

标签: c# .net .net-core .net-assembly


【解决方案1】:

这是因为编译器使用预处理器指令根据配置生成不同的 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 提出一个问题,他们会按预期实现这一点。

【讨论】:

  • 是的,但我正在寻找调试模式的调试配置和预期的 IL 代码。
  • @TarasKovalenko 您能否检查您的 msbuild/csc 标志以确保实际设置了 DEBUG
  • @TarasKovalenko 我怀疑该工具是否正确
  • 感谢您更新您的答案;)
  • 为此我在 SharpLab 上创建了一个新问题:github.com/ashmind/SharpLab/issues/161
【解决方案2】:

有两个概念似乎让您感到困惑。

  1. 发布/调试编译模式:

    这控制编译器是否将调试信息发送到代码中(例如用于设置断点的NOP 指令)以及其他一些方面,例如在编译器和 JIT 级别上执行的优化。这是基于 C# 编译器的 /debug 参数。

  2. 预处理器符号:

    这控制了为编译运行定义的符号。默认情况下,在使用 Visual Studio 创建 C# 项目时,它们在调试模式下设置为 DEBUGTRACE,在发布模式下设置为 TRACE。然后使用这些符号来解析您正在使用的 #if 指令。这是基于 C# 编译器的 /define 参数

您的情况似乎是您的工具告诉 C# 编译器以调试/发布模式运行,但未在参数中提供预期的预处理器符号 (DEBUG)。因此,您会在 Release 和 Debug 配置中看到非DEBUG 代码。

另请参阅:Microsoft docs: C# compiler options by category

【讨论】:

    猜你喜欢
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-06
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多