【问题标题】:Is it possible to create a Debug-only method in .NET?是否可以在 .NET 中创建仅调试方法?
【发布时间】:2009-09-17 15:31:47
【问题描述】:

是否可以创建像System.Diagnostics.Debug 类那样执行调试辅助的方法?

我正在寻找一种方法来构造一个方法,当由定义了 DEBUG 条件编译符号的程序集调用时,该方法会导致操作,并且在由未定义符号的程序集调用时是空操作.

如果可能的话,我希望调试方法的调用能够为程序集的发布版本增加最小的开销或增加大小。

为了澄清,调试方法应该在以发布模式编译的程序集中。对方法的调用仅应在从带有在方法调用范围内定义的 DEBUG 符号的程序集调用时生成操作。

【问题讨论】:

    标签: .net debugging


    【解决方案1】:

    Conditional 属性添加到方法中,如下所示:

    [Conditional("DEBUG")]
    public void Whatever() {
        //...
    }
    

    注意方法必须返回void,不能有out参数;否则,将无法删除对它的调用。

    该方法将被编译到程序集中,但符合 CLS 的编译器仅在它们正在编译的程序集定义了 DEBUG 时才会发出对该方法的调用。请注意,C++ 编译器不符合 CLS,并且始终会发出调用。

    【讨论】:

    • +1 指出 Conditional 并非万无一失(这是否意味着它甚至符合 CLI?) C++ 调用 Debug.WriteLine 会发生什么?是所有版本的吗?很高兴您在 :P 中编辑它
    • 我还没有真正尝试过。 ConditionalAttribute 上的 MSDN 页面只是说 C++ 编译器不兼容,没有说明是哪个版本。
    • 正如我在答案 (and will always emit the call) 中所述,C++ 编译器(我相信)将始终发出对 WriteLine 的调用,即使在 Release 中也是如此。
    • 如果应用了 ConditionalAttribute,我认为非 void 或“无参数”方法应该是编译错误。
    【解决方案2】:

    ConditionalAttribute

    顺便说一句,被调用方法的代码保留在程序集中——在编译时删除的是对它的调用

    奖励专题博文:http://blogs.msdn.com/ericlippert/archive/2009/09/10/what-s-the-difference-between-conditional-compilation-and-the-conditional-attribute.aspx

    【讨论】:

      【解决方案3】:

      如果您使用 Reflector 反汇编 System.Diagnostics.Debug 类,您可以看到这是使用 [Conditional("DEBUG")] 属性完成的:

      public sealed class Debug
      {
          private Debug();
          [Conditional("DEBUG")]
          public static void Assert(bool condition);
          // etc...
      }
      

      【讨论】:

        【解决方案4】:

        如果您需要其他签名而不是没有输出参数的 void func(..), 会有什么问题

        MyDebugObject Foo(out int justForGrins)
        {
            justForGrins = <safe value for release builds>;
            MyDebugObject result = <safe value for release builds>;
            #if DEBUG
             .. run code you need for your debugging...
            #endif
             return result;
        }
        

        它比 ConditionalAttribute 更冗长且不那么优雅,但它可以让您更灵活的签名。

        【讨论】:

          【解决方案5】:

          为什么不尝试这样的事情呢?

          #if DEBUG
                  private void DebugLog(string message)
                  {
                      // do whatever u want.
                  }
          #endif
          

          【讨论】:

          • 这会产生一个问题,即在非调试版本下编译时该方法不存在。任何试图调用此方法的代码都不会编译。 Debug 类具有可以从调试代码调用的方法,但在编译发布代码时会删除这些调用。
          • @Tragedian 即使有你提到的问题,在某些情况下这也是一个更好的解决方案。只要考虑到您提到的内容,这是一个有效的答案。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-09-23
          相关资源
          最近更新 更多