Effective C#:使用Conditional特性而不是#if条件编译

     #if/#endif语句在日常编程中经常会被用到,尤其是想要基于同一份源代码生成不同的编译结果,eg.debug版和release版.但是我们经常遇到的情况是,#if/#endif

成为一种习惯的时候,就会被无限制的滥用,代码进而难以理解或调试。所以,在需要编写条件代码块的时候,提倡使用Conditional特性代替#if条件编译。

     #if条件语句

     1.#if条件是存在于方法体内的,在方法实现的过程中,对应具体的条件限制,添加检查操作。

    

public void Func()
{
      string msg = null;
#if DEBUG
      msg = GetDiagnostics();
#endif

      ...      
}

     在debug版本中,才会执行诊断操作,看起来都很正常,但是往往的结果,却并不是这样。

public void Func()
{
      string msg = null;
#if DEBUG
      msg = GetDiagnostics();
#endif
   
      Console.WriteLine(msg);
      ...
}

     在release版本中,这样类似的操作是有问题的。

     2.#if条件的作用域范围是整个方法体。

public void Func()
{
#if DEBUG
      ...
#endif
}

    在debug版本和release版本中都会调用Func方法,虽然在release版本中,Func什么都没有做,但是方法的加载,JIT编译和调用都仍旧是有些开销的。

    Conditional特性

    来看一个例子

[Conditional("DEBUG")]
private void Func()
{
    ...
}

    Conditional限制了整个方法的调用,无论是否定义了DEBUG环境变量,Func方法都将被编译至程序集中,但是如果没有被调用,Func方法并不会被加载到内存中,也不会被JIT编译。这也是相比于#if,Conditional特性的优势所在。

   对于应用多个Conditional特性,一般的关系是“或”

[Conditional("DEBUG"),
COnditional("TRACE")]
private void Func()
{
    ...
}

    如果需要“与”的效果,可以自定义符号控制。Conditional特性可以被任何方式定义的符号控制。

#if("DEBUG" && "TRACE")
#define BOTH
#endif

...

[Conditional("BOTH")]
private void Func()
{
    ...
}

    只需要在整个文件头定义自己的符号即可。

    Conditional特性只可以应用在整个方法上,并且任何一个使用Conditional特性的方法都只能返回void类型。也就是说,你不能在方法内的代码块上应用Conditional特性,也不可以在有返回值的方法上应用Conditional特性。

    综上,使用Conditional特性生成的IL要比使用#if条件更有效率。同时,将其限制在函数层面上,可以更加清晰地将条件性的代码分离出来,从而保证良好的代码结构。

原文地址:https://www.cnblogs.com/ByronsHome/p/3383840.html