在现代编程中,'#IF DEBUG'被弃用了吗?

时间:2009-04-27 23:55:27

标签: c#

这是我的第一个StackOverflow问题,所以很好! : - )

我最近在一些C#源代码中遇到了以下示例:

public IFoo GetFooInstance()
{
    #IF DEBUG
        return new TestFoo();
    #ELSE
        return new Foo();
    #ENDIF
}

这引出了我这些问题:

  1. “#IF DEBUG”的使用是否被非正式弃用?如果不是被认为是其使用的良好实施?
  2. 使用类工厂和/或MOQ,RhinoMocks等工具,如何实现上述示例?

6 个答案:

答案 0 :(得分:6)

使用IoC容器,整个函数变得多余,而不是调用GetFooInstance,你的代码类似于:

ObjectFactory.GetInstance<IFoo>();

IoC容器的设置可以是代码或配置文件。

答案 1 :(得分:4)

不。我们一直用它来在我们的组件中撒上诊断信息。例如,我在调试时使用了以下快捷方式:

#if DEBUG
        if( ??? ) System.Diagnostics.Debugger.Break();
#endif

我可以改变的地方???任何相关的表达,如姓名==“爆米花”。这样可以确保没有任何调试代码泄漏到发布版本中。

答案 2 :(得分:1)

就像其他一些海报所提到的那样,我一直使用#if语句进行调试。

您发布的代码样式更多是工厂创建模式,这很常见。我经常使用它,不仅我不认为它被折旧,我认为使用#if和#define语句是我的技巧中的一个重要工具。

我相信CastleWindsor(http://www.castleproject.org/container/index.html)也有一个IoC容器。我相信一般模式是在配置文件中,您声明TestFoo或IFoo将是CastleWindsor初始化IoC容器时创建的类。

答案 3 :(得分:1)

是。我强烈建议使用“#IF DEBUG”除非在极少数情况下

它在C中很常见,但您不应该使用C#等现代语言,原因如下:

  1. 代码(和标题)文件变得噩梦
  2. 很容易犯错并留下/发布版本构建的条件
  3. 测试成为一场噩梦:需要测试许多构建组合
  4. 并非所有代码都经过编译检查,除非您为ALL编译 条件符号!
  5. @ Richard的答案显示了如何使用IoC替换(更清洁)。

答案 4 :(得分:-1)

我强烈反对#if;而是使用带有清单常量的if

#define DEBUG 0   // actually in a header or on a command line

public IFoo GetFooInstance()
{
    if (DEBUG)
        return new TestFoo();
    else
        return new Foo();
}

为什么#IF不好?因为在#IF版本中,并非所有代码都是具体的。对于复杂的,长寿命的代码,bitrot可以设置,然后突然你需要DEBUG但代码不会构建。使用if版本,代码始终构建,并且即使是最小的优化设置,编译器也将完全消除无法访问的代码。换句话说,只要DEBUG 已知始终为0(并且#define将为您执行此操作),则没有运行时成本< / em>使用if

如果您将DEBUG从0更改为1,系统将会构建。

答案 5 :(得分:-2)

你的编译器应该足够聪明,以便弄明白:

final DEBUG=false;
...
if(DEBUG)
    return new debugMeh();
else
    return new meh();

该方法永远不必被调用,实际上可以从最终的程序集中编译出来。

这加上这样一个事实,即使未经优化的性能差异也不会产生任何重大影响,因此使用一些不同的语法大多是不必要的。

编辑:我想在这里指出一些有趣的东西。评论中有人刚说过:

#IF DEBUG
    return new TestFoo();
#ELSE
    return new Foo();
#ENDIF

比这更容易写:

if(DEBUG)
    return new TestFoo();
else
    return new Foo();

我发现人们去捍卫他们做正确事情的方式真是太神奇了。另一个人说他们必须在每个文件中定义一个DEBUG变量。我不确定C#,但在Java中我们通常会添加一个

public static final DEBUG=true;

在我们的记录器或其他中央工厂对象中(尽管我们实际上找到了更好的方法 - 例如使用DI)。

我并不是说C#中不存在相同的设施,我只是惊讶于人们会因为习惯是正确的而去证明他们坚持的解决方案。