.NET 编译器 — DEBUG 与 DEBUG发布
-
09-06-2019 - |
题
多年来,我一直在 VB.NET 中使用 DEBUG 编译器常量将消息写入控制台。我也以类似的方式使用 System.Diagnostics.Debug.Write 。我一直认为,当使用 RELEASE 作为构建选项时,所有这些语句都会被编译器忽略,从而使生产代码免于调试语句的开销。最近,在使用 Silverlight 2 Beta 2 时,我注意到 Visual Studio 实际上附加到了我在公共网站上运行的 RELEASE 版本,并显示了 DEBUG 语句,我认为这些语句甚至没有编译!现在,我的第一个倾向是假设我的环境有问题,但我也想问任何对 System.Diagnostics.Debug 和 DEBUG 构建选项有深入了解的人,我在这里可能会误解什么。
解决方案
首选方法是实际使用条件属性来包装调试调用,而不是使用编译器指令。#ifs 可能会变得棘手,并可能导致奇怪的构建问题。
使用条件属性的示例如下(在 C# 中,但也适用于 VB.NET):
[ Conditional("Debug") ]
private void WriteDebug(string debugString)
{
// do stuff
}
当您在未设置 DEBUG 标志的情况下进行编译时,任何对 WriteDebug 的调用都将被删除,就像假定发生在 Debug.Write() 中一样。
其他提示
我所做的是将 Debug 的调用封装在我自己的类中,并添加预编译器指令
public void Debug(string s)
{
#if DEBUG
System.Diagnostics.Debug(...);
#endif
}
正如您所说,使用 DEBUG 编译器符号实际上会省略程序集中的代码。
我相信 System.Diagnostics.Debug.Write 将始终输出到附加的调试器,即使您是在发布模式下构建的。根据 MSDN 文章:
将有关调试的信息写入 Listeners 集合中的跟踪侦听器。
如果你不想 任何 输出,您需要使用 DEBUG 常量包装对 Debug.Write 的调用,如 Juan 所说:
#if DEBUG
System.Diagnostics.Debug.Write(...);
#endif
我也阅读了这篇文章,它让我相信,当未定义 DEBUG 时,在 System.Debug 函数上声明的 ConditionalAttribute 会导致编译器完全忽略此代码。我认为 TRACE 也是如此。也就是说,System.Diagnostics.Debug 函数必须具有 DEBUG 和 TRACE 的 ConditionalAttributes。我的这个假设是错误的。单独的 Trace 类具有相同的功能,并且这些功能根据 TRACE 常量定义 ConditionalAttribute。
从系统.诊断.调试:_公共共享子写(_消息为字符串_)
来自系统.诊断.跟踪:_ public共享sub Writeline(_消息为字符串_)
看来我最初的假设是正确的,System.Diagnostics.Debug(或system.Diagnostics.Trace)语句实际上不包含在编译中,就好像它们包含在#IF DEBUG(或#IF TRACE)区域中一样。
但我也从你们那里了解到,并验证了 RELEASE 构建本身并不能解决这个问题。至少对于仍然有点不稳定的 Silverlight 项目,您需要进入“高级编译选项...”并确保未定义 DEBUG。
我们从 .NET 1.1/VS2003 跳到了 .NET 3.5/VS2008,所以我认为其中一些以前的工作方式有所不同,但也许它在 2.0/VS2005 中发生了变化。
要选择是否要编译或删除调试信息,
进入项目属性窗口中的“构建”选项卡。
选择正确的配置(Active/Release/debug/all),并确保如果需要该信息,请确保检查“调试常数”,或者如果不需要,请取消选中。
应用更改并重建
根据我的经验,在 VB.NET 中选择“调试”和“发布”没有什么区别。您可以向这两个配置添加自定义操作,但默认情况下我认为它们是相同的。
使用Release肯定不会删除System.Diagnostics.Debug.Write语句。