#if DEBUG 与条件条件(“DEBUG”)
在大型项目中哪个更好用,以及为什么:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
或
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
Which is better to use, and why, on a large project:
#if DEBUG
public void SetPrivateValue(int value)
{ ... }
#endif
or
[System.Diagnostics.Conditional("DEBUG")]
public void SetPrivateValue(int value)
{ ... }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
这实际上取决于您的目的:
#if DEBUG
:此处的代码在发布时甚至不会达到 IL。[Conditional("DEBUG")]
:此代码将到达 IL,但是除非在编译调用方时设置了 DEBUG,否则对该方法的调用将被省略。就我个人而言,我根据情况使用两者:
Conditional("DEBUG") 示例: 我使用这个,这样我就不必在发布期间返回并编辑我的代码,但在调试期间我想要确保我没有犯任何错别字。当尝试在 INotifyPropertyChanged 内容中使用属性名称时,此函数会检查我是否正确键入属性名称。
您确实不想使用
#if DEBUG
创建函数,除非您愿意使用相同的#if DEBUG
包装对该函数的每个调用:与:
#if DEBUG 示例: 我在尝试为 WCF 通信设置不同的绑定时使用它。
在第一个示例中,代码全部存在,但除非打开 DEBUG,否则将被忽略。在第二个示例中,const ENDPOINT 设置为“Localhost”或“BasicHttpBinding”,具体取决于是否设置了 DEBUG。
更新:我正在更新这个答案,以澄清一个重要而棘手的点。如果您选择使用
ConditionalAttribute
,请记住,调用会在编译期间被省略,而不会在运行时。即:MyLibrary.dll
当该库针对发布模式(即没有 DEBUG 符号)进行编译时,它将永远从
A()
内调用B()
省略,即使包含对A()
的调用,因为 DEBUG 是在调用程序集中定义的。It really depends on what you're going for:
#if DEBUG
: The code in here won't even reach the IL on release.[Conditional("DEBUG")]
: This code will reach the IL, however calls to the method will be omitted unless DEBUG is set when the caller is compiled.Personally I use both depending on the situation:
Conditional("DEBUG") Example: I use this so that I don't have to go back and edit my code later during release, but during debugging I want to be sure I didn't make any typos. This function checks that I type a property name correctly when trying to use it in my INotifyPropertyChanged stuff.
You really don't want to create a function using
#if DEBUG
unless you are willing to wrap every call to that function with the same#if DEBUG
:versus:
#if DEBUG example: I use this when trying to setup different bindings for WCF communication.
In the first example, the code all exists, but is just ignored unless DEBUG is on. In the second example, the const ENDPOINT is set to "Localhost" or "BasicHttpBinding" depending on if DEBUG is set or not.
Update: I am updating this answer to clarify an important and tricky point. If you choose to use the
ConditionalAttribute
, keep in mind that calls are omitted during compilation, and not runtime. That is:MyLibrary.dll
When the library is compiled against release mode (i.e. no DEBUG symbol), it will forever have the call to
B()
from withinA()
omitted, even if a call toA()
is included because DEBUG is defined in the calling assembly.嗯,值得注意的是,它们根本不是同一件事。
如果未定义 DEBUG 符号,则在第一种情况下,
SetPrivateValue
本身不会被调用...而在第二种情况下,它将存在,但任何调用者 在没有 DEBUG 符号的情况下进行编译的人将省略这些调用。如果代码及其所有调用者位于同一个程序集中,则这种差异不太重要 - 但这意味着在第一种情况下,您还需要有
#if也围绕调用代码进行调试。
就我个人而言,我推荐第二种方法 - 但您确实需要在头脑中清楚地了解它们之间的区别。
Well, it's worth noting that they don't mean the same thing at all.
If the DEBUG symbol isn't defined, then in the first case the
SetPrivateValue
itself won't be called... whereas in the second case it will exist, but any callers who are compiled without the DEBUG symbol will have those calls omitted.If the code and all its callers are in the same assembly this difference is less important - but it means that in the first case you also need to have
#if DEBUG
around the calling code as well.Personally I'd recommend the second approach - but you do need to keep the difference between them clear in your head.
我确信很多人会不同意我的观点,但是作为一名构建人员,我经常听到“但它可以在我的机器上运行!”,我认为你几乎不应该使用任何一个。如果您确实需要进行测试和调试,请找出一种方法使可测试性与实际的生产代码分开。
在单元测试中通过模拟抽象场景,为您想要测试的一次性场景制作一次性版本,但不要将调试测试放入您为生产版本测试和编写的二进制文件的代码中。这些调试测试只是向开发人员隐藏了可能的错误,因此直到流程后期才发现它们。
I'm sure plenty will disagree with me, but having spent time as a build guy constantly hearing "But it works on my machine!", I take the standpoint that you should pretty much never use either. If you really need something for testing and debugging, figure out a way to make that testability seperate from the actual production code.
Abstract the scenarios with mocking in unit tests, make one off versions of things for one off scenarios you want to test, but don't put tests for debug into the code for binaries which you test and write for production release. These debug tests just hide possible bugs from devs so they aren't found until later in the process.
这个也很有用:
This one can be useful as well:
对于第一个示例,如果未定义
DEBUG
,则SetPrivateValue
将不会存在于构建中,对于第二个示例,调用如果未定义 DEBUG,SetPrivateValue 将不会存在于构建中。
对于第一个示例,您还必须使用
#if DEBUG
包装对SetPrivateValue
的所有调用。在第二个示例中,对
SetPrivateValue
的调用将被省略,但请注意SetPrivateValue
本身仍将被编译。如果您正在构建库,那么引用您的库的应用程序仍然可以使用您的函数(如果满足条件),这非常有用。如果您想省略调用并节省被调用者的空间,您可以结合使用这两种技术:
With the first example,
SetPrivateValue
won't exist in the build ifDEBUG
is not defined, with the second example, calls toSetPrivateValue
won't exist in the build ifDEBUG
is not defined.With the first example, you'll have to wrap any calls to
SetPrivateValue
with#if DEBUG
as well.With the second example, the calls to
SetPrivateValue
will be omitted, but be aware thatSetPrivateValue
itself will still be compiled. This is useful if you're building a library, so an application referencing your library can still use your function (if the condition is met).If you want to omit the calls and save the space of the callee, you could use a combination of the two techniques:
我们假设您的代码还有一个
#else
语句,它定义了一个空存根函数,解决了 Jon Skeet 的观点之一。两者之间还有第二个重要区别。假设
#if DEBUG
或Conditional
函数存在于主项目可执行文件引用的 DLL 中。使用#if
,将根据库的编译设置执行条件评估。使用Conditional
属性,将根据调用者的编译设置执行条件评估。Let's presume your code also had an
#else
statement which defined a null stub function, addressing one of Jon Skeet's points. There's a second important distinction between the two.Suppose the
#if DEBUG
orConditional
function exists in a DLL which is referenced by your main project executable. Using the#if
, the evaluation of the conditional will be performed with regard to the library's compilation settings. Using theConditional
attribute, the evaluation of the conditional will be performed with regard to the compilation settings of the invoker.我有一个 SOAP WebService 扩展,可以使用自定义
[TraceExtension]
记录网络流量。我仅将其用于调试构建,并在发布构建中省略。使用#if DEBUG
包装[TraceExtension]
属性,从而将其从Release 版本中删除。I have a SOAP WebService extension to log network traffic using a custom
[TraceExtension]
. I use this only for Debug builds and omit from Release builds. Use the#if DEBUG
to wrap the[TraceExtension]
attribute thus removing it from Release builds.通常,您会在 Program.cs 中需要它,您希望决定在非调试代码上运行调试,并且大多数情况下在 Windows 服务中运行调试。因此,我创建了一个只读字段 IsDebugMode 并在静态构造函数中设置其值,如下所示。
Usually you would need it in Program.cs where you want to decide to run either Debug on Non-Debug code and that too mostly in Windows Services. So I created a readonly field IsDebugMode and set its value in static constructor as shown below.