.NET编译器--DEBUG与RELEASE的区别

19

多年来我一直在VB.NET中使用DEBUG编译器常量向控制台写入信息,类似地,我也一直在使用System.Diagnostics.Debug.Write。我一直以为,在构建选项中使用RELEASE时,编译器会忽略所有这些语句,从而消除调试语句的开销,使您的产品代码更加轻便。最近,在使用Silverlight 2 Beta 2时,我注意到Visual Studio实际上连接到了一个我从公共网站运行的发布版本,并显示了我认为甚至没有被编译的DEBUG语句!现在,我的第一反应是认为我的环境有问题,但我也想问一下对System.Diagnostics.Debug和DEBUG构建选项有深入了解的人,我可能在这里误解了什么。

7个回答

22

首选方法是使用条件属性来包装您的调试调用,而不是使用编译器指令。#if可能会变得棘手,并导致奇怪的构建问题。

使用条件属性的示例如下(在C#中,但也适用于VB.NET):

[ Conditional("Debug") ]
private void WriteDebug(string debugString)
{
  // do stuff
}

当您在编译时未设置DEBUG标志时,任何对WriteDebug的调用都将被删除,这被认为是使用Debug.Write()发生的情况。


1
我认为使用ConditionalAttribute意味着该方法仍然是实际发布程序集的一部分,只是没有被加载。因此,我想唯一真正的去除调试代码的方法是使用编译器指令? - James

5

请查看 Debug.Write 方法。该方法被标记为

[Conditional("DEBUG")]

属性。

ConditionalAttribute 的 MSDN 帮助文档说明:

指示编译器忽略方法调用或属性,除非定义了指定的条件编译符号

构建配置是发布版还是调试版并不重要,重要的是其中是否定义了 DEBUG 符号。


2
我也读了这篇文章,并且认为当未定义DEBUG时,声明在System.Debug函数上的ConditionalAttribute会导致编译器完全省略此代码。我认为对于TRACE也是如此。也就是说,System.Diagnostics.Debug函数必须具有DEBUG和TRACE的ConditionalAttributes。但我的假设是错误的。单独的Trace类具有相同的函数,并且这些定义了依赖于TRACE常量的ConditionalAttribute。
来自System.Diagnostics.Debug: _ 公共共享子写 ( _ 信息作为字符串 _ )
来自System.Diagnostics.Trace: _ 公共共享子写行 ( _ 信息作为字符串 _ )
因此,我的最初假设是正确的,即System.Diagnostics.Debug(或system.Diagnostics.Trace)语句实际上不包括在编译中,就好像它们包含在#IF DEBUG(或#IF TRACE)区域中一样。
但是,我也从你们这里学到了并验证了,在RELEASE构建本身并不处理这个问题。至少对于仍然有点脆弱的Silverlight项目,您需要进入“高级编译选项...”并确保未定义DEBUG。
我们从.NET 1.1/VS2003跳到了.NET 3.5/VS2008,因此我认为有些事情过去的工作方式不同,但可能在2.0/VS2005中发生了变化。

1
我所做的是将调试调用封装在我自己的类中,并添加一个预编译指令。
public void Debug(string s)
{
#if DEBUG
    System.Diagnostics.Debug(...);
#endif
}

1

选择是否编译或删除调试信息,

进入项目属性窗口中的“构建”选项卡。

选择正确的配置(Active/Release/Debug/All),并确保您勾选了“DEBUG常量”,如果需要信息, 或者取消勾选它,如果不需要。

应用更改并重新构建。


1

使用DEBUG编译器符号将会像你所说的那样,实际上从汇编中省略代码。

我相信System.Diagnostics.Debug.Write将始终输出到已连接的调试器,即使您在发布模式下构建。根据MSDN文章

向Listerners集合中的跟踪侦听器写入有关调试的信息。

如果您不想要任何输出,您需要使用Juan所说的DEBUG常量来包装您对Debug.Write的调用:

#if DEBUG
    System.Diagnostics.Debug.Write(...);
#endif

-6
根据我的经验,在VB.NET中选择调试(Debug)和发布(Release)并没有任何区别。你可以向两个配置都添加自定义操作,但默认情况下它们是相同的。
使用发布(Release)肯定不会删除System.Diagnostics.Debug.Write语句。

它们不是相同的;默认情况下,Release模式确实会删除对Debug.Write的调用,因为该方法应用了ConditionalAttribute。 - Robert Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接