条件("调试")+ #if DEBUG

dev*_*ium 8 .net c# vb.net

我在调试.net 2.0应用程序中看到了以下代码

[Conditional("DEBUG")]
void AssertTableExists() {
    #if DEBUG
        ...
    #endif
}
Run Code Online (Sandbox Code Playgroud)

有没有理由使用#if指令?我的意思是,根据我的理解,只有在定义了DEBUG时才会调用该方法,所以我没有看到在方法体中有#if的意义.

Eri*_*ert 20

巧合的是,我上周碰巧在我的博客上回答了你的问题.

http://ericlippert.com/2009/09/10/whats-the-difference-between-conditional-compilation-and-the-conditional-attribute/

如果方法的主体引用在#if DEBUG指令下声明的实体,则必须使用#if指令.例如

#if DEBUG
static private int testCounter = 1;
#endif

[Conditional("DEBUG")] void CheckConsistency()
{
#if DEBUG
  testCounter++;
#endif
...
Run Code Online (Sandbox Code Playgroud)

如果在方法体中省略了#if DEBUG,则无法在发布版本中编译.


Kon*_*rin 9

实际上有很多不同之处.ConditionalAttribute在代码中看起来更干净,但它有很多限制,至少比#if有一个优势.

  • 如果未定义符号,#if将完全从编译中删除代码.

  • #if使您可以更好地控制粒度 - 您可以在方法或整个方法中包含一行或者甚至是整个类的某些成员.

  • #if允许您编写如下复杂条件:

    #if DEBUG & !NO_NETWORK
    
    Run Code Online (Sandbox Code Playgroud)
  • #if#else#elif允许更复杂的场景.

  • [有条件]仅适用于返回void的单个整体方法.

  • [有条件]包括编译汇编代码但删除对它的所有调用.如果有人引用你的程序集,他会看到标有[条件]的方法并且能够使用它们 - 这是你用#if无法实现的.

用反射器打开.Net Framework程序集很有意思,查找标记为Conditional ["DBG"]的方法并查看它们的用法.他们都没有,甚至是内部的,都在任何地方使用!那是因为微软编译了.Net,没有定义符号"DBG",但实际上他们在开发过程中使用这些方法来调试.Net.

  • 使用[Conditional]标记的相同签名的两种方法是不可能的,但您可以使用#if实现它.

作为最后一点,我必须说,当您在调试版和发布版中获得完全不同的行为时,条件编译有时会玩恶魔游戏,而您只有在部署代码并且用户开始抱怨之后才会发现它.因此,根据经验,尽量避免使用#if更改行为,仅使用它来更改输入数据.

以下是使用#if的示例 - 用于调试和发布版本的不同应用程序配置.

static string ConnectionString
{
#if DEBUG
    get { return "<debug connection string>"; }
#else
    get { return "<release connection string>"; }
#endif
}
Run Code Online (Sandbox Code Playgroud)