【问题标题】:When to use preprocessor directives in .net?何时在 .net 中使用预处理器指令?
【发布时间】:2011-05-12 11:05:32
【问题描述】:

我认为这是一个简单的问题,所以我认为我遗漏了一些明显的东西。我从来没有真正使用过预处理器指令,但我正在查看某人的代码,并认为这是我应该熟悉的东西。

所以我查看了 msdn 示例 here 它有代码:

#define DEBUG
// ...
#if DEBUG
    Console.WriteLine("Debug version");
#endif

我的两个问题是:

  • 在上面的例子中为什么要定义DEBUG?如果您在调试 v. 发布模式下编译,我的印象是?
  • 查看另一个具有#define MYTEST 的示例,然后根据它是否“定义”写入控制台,但这与仅使用变量有何不同?我在这里错过了什么?

【问题讨论】:

    标签: c# .net c-preprocessor preprocessor-directive


    【解决方案1】:

    我用它做了很多事情。我只在调试版本中需要的调试消息;清理临时文件;包括诊断功能或操作。

    【讨论】:

      【解决方案2】:

      我实际上建议使用条件属性而不是内联 #if 语句。

      [Conditional("DEBUG")]
      private void DeleteTempProcessFiles()
      {
      }
      

      这不仅更简洁,而且更易于阅读,因为您最终不会在代码中包含#if、#else。这种风格在正常代码编辑和逻辑流程错误期间都不太容易出错。

      【讨论】:

      • 我不知道这种风格。感谢发帖。
      • 需要注意的是,无论是否满足条件,方法都会一直发出。该属性仅影响是否会发出 对此方法的调用;这样就可以在库中定义一个方法并给它[Conditional("DEBUG")],这将影响针对该库的编译。
      • 太好了,这里还有更多信息stackoverflow.com/q/3788605/932917
      • 该属性有一个令人讨厌的限制(没有构造函数(公平)但方法必须是无效的。
      【解决方案3】:

      我想举一个我在项目中使用预处理器指令的例子。

      我的程序在磁盘上创建了很多中间文件。仅当我的项目处于发布模式时,我才使用#DEBUG 指令删除这些文件,否则我保留这些文件,以便我们可以查看这些中间文件并确定其中发生的情况。

      当我的应用在生产服务器上运行时,我会在发布模式下构建项目,以便在处理完成后删除这些文件。

      #if (DEBUG==false)
          deleteTempFiles()
      #endif
      

      【讨论】:

      • 我通常做i#f !DEBUG,我知道同样的事情,但稍微苗条
      • @Neil,您的方式也是正确的,但我更喜欢 DEBUG=false,因为它更易于阅读和理解。
      • 我强烈建议不要在调试配置中禁用任何生产代码,因为它可能会产生您在调试时永远不会得到的副作用(是的,我知道它不应该,但是来吧我们知道生活,不是吗?)。对于您的示例,我会以相反的方式进行操作:如果设置了 DEBUG,请将临时文件复制到其他地方以进行检查,然后再进行检查。尽管我承认在某些情况下您必须模拟事物(事务服务等)。
      【解决方案4】:

      通常,可选/条件编译符号将由构建脚本提供。很少见到#define,除了非常调试代码(如果你明白我的意思的话)。

      重新使用变量;我经常使用这样的条件来处理必须在不同运行时(mono、cf、silverlight 等)上运行的代码。一个变量是不够的,因为代码无法编译针对错误的平台(缺少类型/方法等)。

      在给出的示例中,我可能只使用Debug.WriteLine;因为这是用[Conditional("DEBUG")] 装饰的,如果在构建时没有定义DEBUG,所有对它的调用都会被自动删除。

      【讨论】:

        【解决方案5】:

        我有一些代码在使用 Mono 环境而不是 CLR 时需要不同的处理 - 因此我的一些模块中有 Mono 指令。我认为这是一个比调试更好的例子

        【讨论】:

        • 如果代码需要不同的处理,你应该在运行时检查你是否在Mono下运行并相应地改变行为;这样,您仍然可以将一个二进制文件发送到所有平台。 (if (Type.GetType("System.MonoType") != null) { ... } 是测试您是否在 Mono 运行时上运行的推荐方法。请注意,在 Mono 上运行并不意味着在 Linux 上运行;Mono 可用于 Windows 以及 OS X 等其他平台。)但是,测试哪个您所在的运行时通常是一个坏主意。如果您正在解决 Mono 错误,请测试错误本身是否存在。
        【解决方案6】:

        在上面的例子中,他们为什么要定义DEBUG?如果您在调试 v. 发布模式下编译,我的印象是?

        可能是因为它是示例代码。它旨在展示#ifdef 和朋友的工作方式。我不希望你在源文件中定义这样的符号,除非是为了快速测试。

        查看另一个具有“#define MYTEST”的示例,然后根据它是否“定义”写入控制台,但这与仅使用变量有何不同?我在这里错过了什么?

        如果在编译时未定义 MYTEST,编译器实际上不会发出 #if#endif 块之间的代码。因此得到的 IL 会更小。

        另外,请注意这些不是 C# 中的预处理器指令

        【讨论】:

        【解决方案7】:

        如果你使用变量,你的所有代码都会被编译,当你使用预处理器指令时,只有部分代码包含在可执行文件/dll中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多