条件(“调试”)+ #if DEBUG

时间:2009-09-20 23:42:32

标签: c# .net vb.net

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

[Conditional("DEBUG")]
void AssertTableExists() {
    #if DEBUG
        ...
    #endif
}

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

2 个答案:

答案 0 :(得分: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
...

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

答案 1 :(得分:9)

实际上存在很多差异。 ConditionalAttribute在代码中看起来更干净,但它有很多限制,至少比#if。

有一个优势
  • #if 如果未定义符号,则会从编译中完全删除代码。

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

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

    #if DEBUG & !NO_NETWORK
    
  • #if #else #elif 以允许更复杂的方案。

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

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

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

  • 使用 [有条件] 标记相同签名的方法是不可能的,但您可以使用 #if 来实现。

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

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

static string ConnectionString
{
#if DEBUG
    get { return "<debug connection string>"; }
#else
    get { return "<release connection string>"; }
#endif
}