编译条件 - 最佳实践

时间:2018-04-06 17:38:27

标签: c# unit-testing

我使用控制台应用进行单元测试。因此,无论我想在哪里进行单元测试,我都会使用像这样的编译条件

#if UnitTest
                    Console.WriteLine("Invoke: Method 1 Result");
#endif

这很好用,但它会造成混乱和丑陋的代码。对于我来说,调用下面的内容会有多么糟糕,资源有多少。

    public static class UnitTest
    {
        public static void Add(string value)
        {
#if UnitTest
            Console.WriteLine(value);
#endif
        }
    }

然后,当我想要进行单元测试时,我只需要打电话。

UnitTest.Add("Invoke: Method 1 Result");

1 个答案:

答案 0 :(得分:3)

如此接近

正确的方法是

public static class UnitTest
{
  [Conditional("UnitTest")]
  public static void Log(string s)
  {
    Console.WriteLine(s);
  }
}

编译器将删除未定义UnitTest.Log()的源代码中对UnitTest的所有调用。

  

显然,我正在调用一种什么都不做的方法。

这是条件属性的好处。编译器完全删除了调用

顺便说一下,这就是Debug.Assert的工作原理。如果未定义DEBUG,则完全删除断言。

这样做的好处是不会在调用空方法的情况下乱丢您的发行版本。它的缺点是,如果您正在调试发布版本,则不能在已删除的方法上放置断点。此外,请记住,副作用也被删除;永远不会:

Debug.Assert(++x == 10);

因为++x不会在发布版本中发生,但会在调试版本中发生。

说到这,你可能想知道,我可以这样做吗?

class C { 
  #if UnitTest
    static int counter = 0;
  #endif
  ...
  UnitTest.Log("Logger logged " + (++counter) + " logs!");

给出一些想法。这应该有用吗?请记住,就像编译器编写者一样

一旦您认为您知道编译器应该在这里做什么,请检查您的答案:

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